APUE course source code
guowenxue
2 days ago 68826376ee5f47783c644c6604f4411ec747cd7e
Add UDP DNS client source code
4 files added
29 files renamed
470 ■■■■■ changed files
project/3.dnsclient/dnsclient.c 44 ●●●●● patch | view | raw | blame | history
project/3.dnsclient/makefile 27 ●●●●● patch | view | raw | blame | history
project/3.dnsclient/udp_dns.c 376 ●●●●● patch | view | raw | blame | history
project/3.dnsclient/udp_dns.h 23 ●●●●● patch | view | raw | blame | history
project/4.mqttd/booster/config.c patch | view | raw | blame | history
project/4.mqttd/booster/config.h patch | view | raw | blame | history
project/4.mqttd/booster/ds18b20.c patch | view | raw | blame | history
project/4.mqttd/booster/ds18b20.h patch | view | raw | blame | history
project/4.mqttd/booster/ini_dictionary.c patch | view | raw | blame | history
project/4.mqttd/booster/ini_dictionary.h patch | view | raw | blame | history
project/4.mqttd/booster/iniparser.c patch | view | raw | blame | history
project/4.mqttd/booster/iniparser.h patch | view | raw | blame | history
project/4.mqttd/booster/leds.c patch | view | raw | blame | history
project/4.mqttd/booster/leds.h patch | view | raw | blame | history
project/4.mqttd/booster/logger.c patch | view | raw | blame | history
project/4.mqttd/booster/logger.h patch | view | raw | blame | history
project/4.mqttd/booster/makefile patch | view | raw | blame | history
project/4.mqttd/booster/proc.c patch | view | raw | blame | history
project/4.mqttd/booster/proc.h patch | view | raw | blame | history
project/4.mqttd/booster/sht20.c patch | view | raw | blame | history
project/4.mqttd/booster/sht20.h patch | view | raw | blame | history
project/4.mqttd/etc/mqttd.conf patch | view | raw | blame | history
project/4.mqttd/makefile patch | view | raw | blame | history
project/4.mqttd/mqttd.c patch | view | raw | blame | history
project/4.mqttd/openlibs/cjson/build.sh patch | view | raw | blame | history
project/4.mqttd/openlibs/libgpiod/build.sh patch | view | raw | blame | history
project/4.mqttd/openlibs/makefile patch | view | raw | blame | history
project/4.mqttd/openlibs/mosquitto/build.sh patch | view | raw | blame | history
project/4.mqttd/openlibs/openssl/build.sh patch | view | raw | blame | history
project/4.mqttd/openlibs/sqlite/build.sh patch | view | raw | blame | history
project/4.mqttd/openlibs/sqlite/makefile patch | view | raw | blame | history
project/4.mqttd/tools/publisher.sh patch | view | raw | blame | history
project/4.mqttd/tools/subsciber.sh patch | view | raw | blame | history
project/3.dnsclient/dnsclient.c
New file
@@ -0,0 +1,44 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT Studio
 *                  All rights reserved.
 *
 *       Filename:  dnsclient.c
 *    Description:  This file is DNS client API test entry(main) file
 *
 *        Version:  1.0.0(10/29/2018)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2018-10-28 01:38:08 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include "udp_dns.h"
int main(int argc,char* argv[])
{
    char                 *hostname;
    char                  ipaddr[IPADDR_LEN];
    if(argc != 2)
    {
        printf("Usage: %s [domain]\n", argv[0]);
        return 1;
    }
    hostname=argv[1];
    memset( ipaddr, 0, sizeof(ipaddr) );
    query_dns("114.114.114.114", hostname, ipaddr, IPADDR_LEN);
    printf("DNS query: %s->%s\n", hostname, ipaddr);
    return 0;
}
project/3.dnsclient/makefile
New file
@@ -0,0 +1,27 @@
#********************************************************************************
#      Copyright:  (C) 2023 LingYun IoT System Studio
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This file used to compile all the C file to respective binary,
#                  and it will auto detect cross compile or local compile.
#
#        Version:  1.0.0(11/08/23)
#         Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "11/08/23 16:18:43"
#
#*******************************************************************************
APP_NAME=dnsclient
PRJ_PATH=$(shell pwd)
CFLAGS=-Wall -Werror
SRC_FILES = $(wildcard *.c)
all: ${SRC_FILES}
    $(CC) $(CFLAGS) -o ${APP_NAME} $^ $(LDFLAGS)
clean:
    rm -f ${APP_NAME}
project/3.dnsclient/udp_dns.c
New file
@@ -0,0 +1,376 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT Studio
 *                  All rights reserved.
 *
 *       Filename:  udp_dns.c
 *    Description:  This file is DNS client API based on UDP socket
 *
 *        Version:  1.0.0(10/29/2018)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2018-10-28 01:38:08 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "udp_dns.h"
/*+-----------------------------------------------------------------------------------+
 *| DNS Protocal packet format definition
 *| Reference:  https://www.ietf.org/rfc/rfc1035.txt
 *|             https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf
 *+-----------------------------------------------------------------------------------+
 */
/*
   DNS packet format:
   +---------------------+
   |        Header       |
   +---------------------+
   |       Question      | the question for the name server
   +---------------------+
   |        Answer       | RRs answering the question
   +---------------------+
   |      Authority      | RRs pointing toward an authority
   +---------------------+
   |      Additional     | RRs holding additional information
   +---------------------+
   Header section format:
   1  1  1  1  1  1
   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                      ID                       |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                    QDCOUNT                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                    ANCOUNT                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                    NSCOUNT                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                    ARCOUNT                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   Question section format:
   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                                               |
   /                     QNAME                     /
   /                                               /
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                     QTYPE                     |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                     QCLASS                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   Resource record format:
   1  1  1  1  1  1
   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                                               |
   /                                               /
   /                      NAME                     /
   |                                               |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                      TYPE                     |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                     CLASS                     |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                      TTL                      |
   |                                               |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                   RDLENGTH                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
   /                     RDATA                     /
   /                                               /
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   */
void dump_buf(const char *prompt, char *data, int len)
{
    int      i;
    if(prompt)
    {
        printf("%s", prompt);
    }
    for(i=0; i<len; i++)
    {
        printf("%02x ", data[i]);
    }
    printf("\n");
}
int fill_dns_head(char *packet, int size)
{
    unsigned short   tmp;
    int              ofset = 0;
    if( !packet || size<DNS_HEAD_MIN )
    {
        printf("Invalid input arguments in %s()\n", __FUNCTION__);
        return -1;
    }
    /* DNS Head: Transaction ID */
    srand((int)time(0));
    tmp = (unsigned short)random();
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    /* DNS Head: Flags */
    tmp = 0x0001; /* MSB */
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    /* DNS Head: Questions */
    tmp = 0x0100; /* MSB */
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    /* DNS Head: Answer RRs */
    tmp = 0x0000;
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    /* DNS Head: Authority RRs */
    tmp = 0x0000;
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    /* DNS Head: Additional RRs */
    tmp = 0x0000;
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    //dump_buf("DNS packet head: \n", packet, ofset);
    return ofset;
}
int fill_dns_question_qtype_qclass(char *packet, int size)
{
    unsigned short   tmp;
    int              ofset = 0;
    if( !packet || size<DNS_HEAD_MIN )
    {
        printf("Invalid input arguments in %s()\n", __FUNCTION__);
        return -1;
    }
    /* DNS QType: 0x0001(A record)   0x0005(CNAME)*/
    tmp = 0x0100; /* MSB */
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    /* DNS QClass, 0x0001: representing Internet addresses */
    tmp = 0x0100; /* MSB */
    memcpy(&packet[ofset], &tmp, 2);
    ofset += 2;
    //dump_buf("DNS packet tail: \n", packet, ofset);
    return ofset;
}
/* www.baidu.com ==> 3www5baidu3com0 */
int fill_dns_question_qname(char *domain, char *packet, int size)
{
    int           ofset = 0;
    const char   *start;
    char         *ptr;
    int           len;
    /* Check arguments */
    if( !domain || !packet || size<strlen(domain) )
    {
        return -1;
    }
    start = domain;
    while( (ptr=(strchr(start, '.'))) != NULL )
    {
        len=ptr-start; /* get segemnent length by '.'  */
        packet[ofset++] = len;
        len = ptr-start;
        strncpy(&packet[ofset], start, len); /* copy segemnent string  */
        ofset += len;
        start = ptr + 1; /* let start point to next character follow '.'  */
    }
    /* last segemnent by '.' is pointed by start */
    len = strlen(domain)- (start-domain);
    packet[ofset++] = len;
    /* check strncpy buffer limits  */
    if(size-ofset < len)
        len = size-ofset;
    strncpy(&packet[ofset], start, len);
    ofset += len;
    packet[ofset++] = 0x00;
    return ofset;
}
int query_dns(char *dns_server_ip, char *domain, char *ipaddr, int ipaddr_size)
{
    int                    sockfd;
    char                   msg_buf[512];
    int                    ofset = 0;
    int                    rv = -1;
    struct sockaddr_in     servaddr;
    if(!domain || !ipaddr || strlen(domain)<=0 || ipaddr_size<IPADDR_LEN)
    {
        printf("Invalid input arguments\n");
        return -1;
    }
    memset(ipaddr, 0, ipaddr_size);
    /*+--------------------------------------------------------------------------------------------------------------
     *| Parser baidu.com:
     *| Send DNS Query Packet:
     *|    a7 c3 01 00 00 01 00 00 00 00 00 00 05 62 61 69 64 75 03 63 6f 6d 00 00 01 00 01
     *|
     *| Header section format:
     *|  Session ID(2B): A7 C3
     *|        Flag(2B): 01 00
     *|     QDCOUNT(2B): 01 00        1 entry in the question section
     *|     ANCOUNT(2B): 00 00        0 resource records in the answer section
     *|     NSCOUNT(2B): 00 00        0 resource records in the authority records section
     *|     ARCOUNT(2B): 00 00        0 resource records in the additional records section
     *|
     *| Question section format:
     *|       QNAME(nB): 05 62 61 69 64 75 03 63 6f 6d 00:   05baidu03com0
     *|       QTYPE(2B): 00 01        1: (A record)
     *|      QCLASS(2B): 00 01        1: (Internet addresses)
     *+--------------------------------------------------------------------------------------------------------------
     */
    rv=fill_dns_head(&msg_buf[ofset], sizeof(msg_buf)-ofset);
    if( rv < 0 )
    {
        printf("Fill DNS head failure\n");
        return -2;
    }
    ofset += rv;
    rv = fill_dns_question_qname(domain, &msg_buf[ofset], sizeof(msg_buf)-ofset);
    if(rv < 0)
    {
        printf("Fill DNS Question Qname failure\n");
        return -2;
    }
    ofset += rv;
    rv= fill_dns_question_qtype_qclass(&msg_buf[ofset], sizeof(msg_buf)-ofset);
    if( rv < 0 )
    {
        printf("Fill DNS Question QType and QClass\n");
        return -3;
    }
    ofset += rv;
    //dump_buf("DNS packet : \n", msg_buf, ofset);
    if ( (sockfd=socket(PF_INET, SOCK_DGRAM, 0)) < 0 )
    {
        printf("Create UDP socket failure: %s\n", strerror(errno));
        return -4;
    }
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(53); /*DNS default port 53 */
    servaddr.sin_addr.s_addr = inet_addr(dns_server_ip);
    if( sendto(sockfd, msg_buf, ofset, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 )
    {
        printf("Send DNS packet to DNS server[%s] failure: %s\n", dns_server_ip, strerror(errno));
        return -5;
    }
    if( (rv=recvfrom(sockfd, msg_buf, sizeof(msg_buf), 0, NULL, NULL) ) < 0 )
    {
        printf("Receive DNS reply from DNS server[%s] failure: %s\n", dns_server_ip, strerror(errno));
        return -6;
    }
    /*+--------------------------------------------------------------------------------------------------------------
     *| Receive DNS Server Reply Packet:
     *|    a7 c3 81 80 00 01 [00 02] 00 00 00 00 05 62 61 69 64 75 03 63 6f 6d 00 00 01 00 01
     *|    c0 0c 00 01 00 01 00 00 00 21 00 04 dc b5 39 d8 c0 0c 00 01 00 01 00 00 00 21 00 04 7b 7d 73 6e
     *| Question Section: a7 c3 ... 00 01, but bytes[8:7] is reply resource entries, here is [00 02] so get 2 entries
     *|
     *|                     First resource
     *| Name Pointer(2B): c0 0c
     *|         Type(2B): 01 00
     *|            Class: 01 00
     *|          TTL(4B): 00 00 00 21
     *|     RDLENGTH(2B): 00 04
     *|       IP address: dc b5 39 d8   "220.181.57.216"
     *|
     *|                    Second resource
     *| Name Pointer(2B): c0 0c
     *|         Type(2B): 01 00
     *|            Class: 01 00
     *|          TTL(4B): 00 00 00 21
     *|     RDLENGTH(2B): 00 04
     *|       IP address: 7b 7d 73 6e   "123.125.115.110"
     *|
     *+--------------------------------------------------------------------------------------------------------------
     */
    //dump_buf("Recieve DNS reply: \n", msg_buf, rv);
    /* 1, Reply resource will followed by request packet
     * 2, 2B Name Pointer + 2B Type+2B Class + 4B TTL + 2B RDlength = 12B */
    ofset += 12;
    snprintf(ipaddr, ipaddr_size, "%u.%u.%u.%u", (uint8_t)msg_buf[ofset], (uint8_t)msg_buf[ofset+1],
            (uint8_t)msg_buf[ofset+2], (uint8_t)msg_buf[ofset+3]);
#if 0
    {
        short                  records = 0;
        records = *(short *)&msg_buf[7];
        printf("DNS server[%s] resolve domain \"%s\" get %d records:\n", dns_server_ip, domain, records);
        while( records-- )
        {
            printf("%u.%u.%u.%u\n", (uint8_t)msg_buf[ofset], (uint8_t)msg_buf[ofset+1],
                    (uint8_t)msg_buf[ofset+2], (uint8_t)msg_buf[ofset+3]);
            ofset += 16;
        }
    }
#endif
    close(sockfd);
    return 0;
}
project/3.dnsclient/udp_dns.h
New file
@@ -0,0 +1,23 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT Studio
 *                  All rights reserved.
 *
 *       Filename:  udp_dns.h
 *    Description:  This file is DNS client API based on UDP socket
 *
 *        Version:  1.0.0(10/29/2018)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2018-10-28 01:38:08 PM"
 *
 ********************************************************************************/
#ifndef __DNS_API_
#define __DNS_API_
#define IPADDR_LEN        16
#define DNS_HEAD_MIN      12
#define DNS_TAIL_MIN      5
int query_dns(char *dns_server_ip, char *domain, char *ipaddr, int ipaddr_size);
#endif
project/4.mqttd/booster/config.c
project/4.mqttd/booster/config.h
project/4.mqttd/booster/ds18b20.c
project/4.mqttd/booster/ds18b20.h
project/4.mqttd/booster/ini_dictionary.c
project/4.mqttd/booster/ini_dictionary.h
project/4.mqttd/booster/iniparser.c
project/4.mqttd/booster/iniparser.h
project/4.mqttd/booster/leds.c
project/4.mqttd/booster/leds.h
project/4.mqttd/booster/logger.c
project/4.mqttd/booster/logger.h
project/4.mqttd/booster/makefile
project/4.mqttd/booster/proc.c
project/4.mqttd/booster/proc.h
project/4.mqttd/booster/sht20.c
project/4.mqttd/booster/sht20.h
project/4.mqttd/etc/mqttd.conf
project/4.mqttd/makefile
project/4.mqttd/mqttd.c
project/4.mqttd/openlibs/cjson/build.sh
project/4.mqttd/openlibs/libgpiod/build.sh
project/4.mqttd/openlibs/makefile
project/4.mqttd/openlibs/mosquitto/build.sh
project/4.mqttd/openlibs/openssl/build.sh
project/4.mqttd/openlibs/sqlite/build.sh
project/4.mqttd/openlibs/sqlite/makefile
project/4.mqttd/tools/publisher.sh
project/4.mqttd/tools/subsciber.sh