source: umon/main/common/dns.c

Last change on this file was a7b6f00, checked in by Ed Sutter <edsutterjr@…>, on 08/04/15 at 01:35:50

tree cleanup using 'astyle --unpad-paren --align-pointer=name --lineend=linux --add-brackets --convert-tabs --style=knf -A4 FILENAME'

  • Property mode set to 100644
File size: 21.1 KB
Line 
1/**************************************************************************
2 *
3 * Copyright (c) 2013 Alcatel-Lucent
4 *
5 * Alcatel Lucent licenses this file to You under the Apache License,
6 * Version 2.0 (the "License"); you may not use this file except in
7 * compliance with the License.  A copy of the License is contained the
8 * file LICENSE at the top level of this repository.
9 * You may also obtain a copy of the License at:
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 **************************************************************************
20 *
21 * dns.c:
22 *
23 * This file implements a basic DNS client and some form of a multicast-DNS
24 * reponder.  The functionality provides the basic ability to retrieve an IP
25 * address from a domain name.
26 * Refer to RFC 1035 section 4.1 for the packet format.
27 *
28 *
29 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
30 *
31 */
32#include "config.h"
33#if INCLUDE_DNS
34#include "endian.h"
35#include "genlib.h"
36#include "stddefs.h"
37#include "ether.h"
38#include "cli.h"
39#include "timer.h"
40
41const char mDNSIp[] = { 224, 0, 0, 251 };
42const char mDNSMac[] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb };
43
44char *dnsErrStr(int errno);
45
46short DnsPort;
47static unsigned short dnsId;
48static unsigned long dnsIP;
49static char dnsErrno, dnsWaiting, dnsCacheInitialized;
50static struct dnscache hostnames[MAX_CACHED_HOSTNAMES];
51
52/* ip_to_bin...
53 * Essentially identical to IpToBin() in ethernet.c, but without
54 * the error message.
55 */
56int
57ip_to_bin(char *ascii,uchar *binary)
58{
59    int i, digit;
60    char    *acpy;
61
62    acpy = ascii;
63    for(i=0; i<4; i++) {
64        digit = (int)strtol(acpy,&acpy,10);
65        if(((i != 3) && (*acpy++ != '.')) ||
66                ((i == 3) && (*acpy != 0)) ||
67                (digit < 0) || (digit > 255)) {
68            return(-1);
69        }
70        binary[i] = (uchar)digit;
71    }
72    return(0);
73}
74
75
76/* getHostAddr():
77 * This function is a simplified version of gethostbyname().
78 * Given a domain name, this function will first query a
79 * locally maintained cache then, if not found there, it will
80 * issue a DNS query to retrieve the hosts IP address.
81 */
82unsigned long
83getHostAddr(char *hostname)
84{
85    short   port;
86    struct ip *ipp;
87    struct Udphdr *udpp;
88    struct dnshdr *dnsp;
89    struct elapsed_tmr tmr;
90    struct ether_header *enetp;
91    uchar   binenet[8], *enetaddr;
92    unsigned long   srvrip, binip;
93    char    *pp, *np, *srvrname, *dot;
94    int     i, namelen, pktsize, ip_len;
95
96    /* First check to see if the incoming host name is simply a
97     * decimal-dot-formatted IP address.  If it is, then just
98     * convert it to a 32-bit long and return here...
99     */
100    if(ip_to_bin(hostname,(uchar *)&binip) == 0) {
101        return(binip);
102    }
103
104    if(!dnsCacheInitialized) {
105        dnsCacheInit();
106    }
107
108    dnsErrno = DNSERR_NULL;
109
110    /* First try to find the hostname in our local cache...
111     */
112    for(i=0; i<MAX_CACHED_HOSTNAMES; i++) {
113        if(strcmp(hostnames[i].name,hostname) == 0) {
114            return(hostnames[i].addr);
115        }
116    }
117
118    /* If not in the cache, we query the network.  First look
119     * for a DNSSRVR defined in the environment.  If found, use
120     * it; else, use IP broadcast.
121     */
122
123    /* See if this is a mDNS request...
124     */
125    if(strstr(hostname,".local")) {
126        DnsPort = port = DNSMCAST_PORT;
127        srvrip = htonl(DNSMCAST_IP);
128        memcpy((char *)binenet,(char *)mDNSMac,sizeof(mDNSMac));
129        enetaddr = binenet;
130    } else {
131        port = IPPORT_DNS;
132        DnsPort = port+1;
133        srvrname = getenv("DNSSRVR");
134        if(srvrname == (char *)0) {
135            srvrip = 0xffffffff;
136        } else {
137            if(IpToBin(srvrname,(uchar *)&srvrip) < 0) {
138                return(0);
139            }
140        }
141
142        /* Get the ethernet address for the IP:
143         */
144        enetaddr = ArpEther((uchar *)&srvrip,binenet,0);
145        if(!enetaddr) {
146            printf("ARP failed for 0x%x\n",srvrip);
147            return(0);
148        }
149    }
150
151    /* Retrieve an ethernet buffer from the driver and populate the
152     * ethernet level of packet:
153     */
154    enetp = (struct ether_header *) getXmitBuffer();
155    memcpy((char *)&enetp->ether_shost,(char *)BinEnetAddr,6);
156    memcpy((char *)&enetp->ether_dhost,(char *)binenet,6);
157    enetp->ether_type = htons(ETHERTYPE_IP);
158
159    /* Move to the IP portion of the packet and populate it
160     * appropriately:
161     */
162    ipp = (struct ip *)(enetp + 1);
163    ipp->ip_vhl = IP_HDR_VER_LEN;
164    ipp->ip_tos = 0;
165    ipp->ip_id = ipId();
166    ipp->ip_off = 0;
167    ipp->ip_ttl = UDP_TTL;
168    ipp->ip_p = IP_UDP;
169    memcpy((char *)&ipp->ip_src.s_addr,(char *)BinIpAddr,4);
170    memcpy((char *)&ipp->ip_dst.s_addr,(char *)&srvrip,4);
171
172    /* Now UDP...
173     */
174    udpp = (struct Udphdr *)(ipp + 1);
175    udpp->uh_sport = htons(DnsPort);
176    udpp->uh_dport = htons(port);
177
178    /* Finally, the DNS data ...
179     */
180    dnsp = (struct dnshdr *)(udpp+1);
181
182    /* Build the message.  This query supports a single internet
183     * host-address question.
184     *
185     * Fixed header...
186     */
187    dnsId = ipId();
188    dnsp->id = htons(dnsId);        /* Unique id */
189    dnsp->param = 0;                /* Parameter field */
190    dnsp->num_questions = htons(1); /* # of questions */
191    dnsp->num_answers = 0;          /* # of answers */
192    dnsp->num_authority = 0;        /* # of authority */
193    dnsp->num_additional = 0;       /* # of additional */
194
195    /* The formatted name list..
196     * Each name is preceded by a single-byte length, so for our
197     * query, the list is "LNNNLNNNLNNN0", where...
198     *  'L' is the single-byte length of the name.
199     *  'NN..N' is variable-lenght domain.
200     *  '0' is the length of the next name in the list; hence,
201     *      indicating the end of the list.
202     *
203     * For each '.' (dot)  in the hostname, there is a
204     * LNNN pair.
205     */
206    pp = (char *)dnsp->question;
207    np = (char *)hostname;
208    namelen = strlen(hostname);
209    do {
210        dot = strchr(np,'.');
211        if(dot) {
212            *pp++ = dot-np;
213            memcpy(pp,np,dot-np);
214            pp += (dot-np);
215            np = dot + 1;
216        } else {
217            *pp++ = strlen(np);
218            strcpy(pp,np);
219        }
220    } while(dot);
221
222
223    /* Since the size of the name can be arbitrary (not aligned),
224     * we must populate the TYPE and CLASS fields one byte at
225     * a time...
226     */
227    pp += (strlen(np) + 1);
228    *pp++ = 0;
229    *pp++ = 1;  /* type = 'A' (host address) */
230    *pp++ = 0;
231    *pp = 1;    /* class = 'IN' (the internet) */
232
233    /* Send the DNS query:
234     * Total message size is...
235     * FIXED_HDR_SIZE + NAME_SIZE + TYPE_SIZE + CLASS_SIZE + (NAMELEN_SIZE*2)
236     * where...
237     *  FIXED_HDR_SIZE  = 12
238     *  NAME_SIZE       = strlen(hostname) = namelen
239     *  TYPE_SIZE       = sizeof(short) = 2
240     *  CLASS_SIZE      = sizeof(short) = 2
241     *  NAMELEN_SIZE    = sizeof(char) = 1
242     *
243     * There are 2 name lengths.  The first one is the size of the host
244     * name we are querying for and the second one is zero (indicating no
245     * more names in the list).
246     * So, the total length of the packet is <namelen + 18>.
247     */
248
249    pktsize = namelen+18;
250    ip_len = sizeof(struct ip) + sizeof(struct Udphdr) + pktsize;
251    ipp->ip_len = htons(ip_len);
252    udpp->uh_ulen = htons((ushort)(ip_len - sizeof(struct ip)));
253
254    ipChksum(ipp);          /* Compute csum of ip hdr */
255    udpChksum(ipp);         /* Compute UDP checksum */
256
257//  printf("Sending DNS rqst id=%04x (%d %d)\n",dnsId,pktsize,ip_len);
258
259    dnsWaiting = 1;
260    sendBuffer(ETHERSIZE + IPSIZE + UDPSIZE + pktsize);
261
262    /* Wait for 3 seconds for a response...
263     */
264    startElapsedTimer(&tmr,3000);
265    while(!msecElapsed(&tmr)) {
266        if(dnsErrno != DNSERR_NULL) {
267            break;
268        }
269        pollethernet();
270    }
271    if(dnsErrno == DNSERR_COMPLETE) {
272        dnsCacheAdd(hostname,dnsIP);
273        shell_sprintf("DNSIP","%d.%d.%d.%d",
274                      IP1(dnsIP),IP2(dnsIP),IP3(dnsIP), IP4(dnsIP));
275        return(dnsIP);
276    } else {
277        if(dnsErrno == DNSERR_NULL) {
278            printf("DNS attempt timeout\n");
279        } else {
280            printf("DNSErr: %s\n",dnsErrStr((int)dnsErrno));
281        }
282        setenv("DNSIP",0);
283    }
284    return(0);
285}
286
287/* Note two different processDNS/processMCASTDNS functions...
288 * processDNS() provides the necessary code to deal with responses
289 * that we should expect to get as a result of issuing a dns request.
290 * processMCASTDNS() provides the necessary code to deal with requests
291 * from other machines querying for our hostname/ip info.
292 */
293
294/* processDNS():
295 * This function provides the recieving half of the DNS query above.
296 */
297int
298processDNS(struct ether_header *ehdr,ushort size)
299{
300    int     i;
301    char    *pp;
302    struct  ip *ihdr;
303    struct  Udphdr *uhdr;
304    struct  dnshdr *dhdr;
305    unsigned short  rtype, qtot, atot;
306
307    if(dnsWaiting == 0) {
308        return(0);
309    }
310
311    dnsWaiting = 0;
312    ihdr = (struct ip *)(ehdr + 1);
313    uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr));
314    dhdr = (struct dnshdr *)(uhdr + 1);
315
316//  printf("DNS: (%d)\n",size);
317//  printf("  dnsid: %04x\n",htons(dhdr->id));
318//  printf("  param: %04x\n",htons(dhdr->param));
319//  printf("  quest: %04x\n",htons(dhdr->num_questions));
320//  printf("  answe: %04x\n",htons(dhdr->num_answers));
321//  printf("  autho: %04x\n",htons(dhdr->num_authority));
322//  printf("  addit: %04x\n",htons(dhdr->num_additional));
323//  printMem(dhdr->question, size - UDPSIZE - IPSIZE - ETHERSIZE - 12,1);
324
325    /* Verify the DNS response...
326     */
327    if((htons(dhdr->param) & 0x8000) == 0) {            /* response? */
328        dnsErrno = DNSERR_NOTARESPONSE;
329        return(0);
330    }
331    if(htons(dhdr->id) != dnsId) {                      /* correct id? */
332        dnsErrno = DNSERR_BADRESPID;
333        return(0);
334    }
335    if((rtype = (htons(dhdr->param) & 0xf)) != 0) {     /* response normal? */
336        switch(rtype) {
337        case 1:
338            dnsErrno = DNSERR_FORMATERR;
339            break;
340        case 2:
341            dnsErrno = DNSERR_SRVRFAILURE;
342            break;
343        case 3:
344            dnsErrno = DNSERR_NAMENOEXIST;
345            break;
346        default:
347            dnsErrno = DNSERR_BADRESPTYPE;
348            break;
349        }
350        return(0);
351    }
352    qtot = htons(dhdr->num_questions);
353    if((atot = htons(dhdr->num_answers)) < 1) {     /* answer count >= 1? */
354        dnsErrno = DNSERR_BADANSWRCOUNT;
355        return(0);
356    }
357
358    /* At this point we can assume that the received packet format
359     * is ok.  Now we need to parse the packet for the "answer" to
360     * our query...
361     */
362
363    /* Set 'pp' to point to the start of the question list.
364     * There should only be one question in the response.
365     */
366    pp = (char *)&dhdr->question;
367
368    /* Skip over the questions:
369     */
370    for(i=0; i<qtot; i++) {
371        while(*pp) {        /* while 'L' is nonzero */
372            pp += (*pp + 1);
373        }
374        pp += 5;            /* Account for last 'L' plus TYPE/CLASS */
375    }
376
377    /* The 'pp' pointer is now pointing a list of resource records that
378     * correspond to the answer list.  It is from this list that we
379     * must retrieve the information we are looking for...
380     */
381
382    for(i=0; i<atot; i++) {
383        unsigned short type, len;
384
385        /* The first portion of the record is the resource domain name
386         * and it may be literal string (a 1-octet count followed by
387         * characters that make up the name) or a pointer to a literal
388         * string.
389         */
390        if((*pp & 0xc0) == 0xc0) {  /* compressed? (section 4.1.4 RFC1035) */
391            pp += 2;
392        } else {
393            while(*pp) {            /* while 'L' is nonzero */
394                pp += (*pp + 1);
395            }
396            pp += 1;
397        }
398        memcpy((char *)&type,pp,2);
399        type = htons(type);
400        pp += 8;
401        memcpy((char *)&len,pp,2);
402        len = htons(len);
403        if((type == TYPE_A) && (len == 4)) {
404            pp += 2;
405            memcpy((char *)&dnsIP,pp,4);
406            dnsIP = htonl(dnsIP);
407        } else {
408            pp += (len+2);
409        }
410    }
411    dnsErrno = DNSERR_COMPLETE;
412    return(0);
413}
414
415/* processMCASTDNS():
416 * If we're here, then we've received a request over the Multi-cast
417 * DNS address for some host name.  If the hostname in this request
418 * matches this board's hostname, then return this board's IP address.
419 * If the shell variable HOSTNAME isn't set, then just return immediately.
420 */
421int
422processMCASTDNS(struct ether_header *ehdr,ushort size)
423{
424    int     l1, ql = 0;
425    struct  ip *ihdr;
426    char    *pp, *myname;
427    struct  Udphdr *uhdr;
428    struct  dnshdr *dhdr;
429
430    ihdr = (struct ip *)(ehdr + 1);
431    uhdr = (struct Udphdr *)(ihdr + 1);
432    dhdr = (struct dnshdr *)(uhdr + 1);
433
434    // If this message is DNS response, branch to processDNS()...
435    if((htons(dhdr->param) & 0x8000) == 0x8000) {
436        processDNS(ehdr,size);
437        return(0);
438    }
439
440    if((myname = getenv("HOSTNAME")) == 0) {
441        return(0);
442    }
443
444    // If this isn't a normal query type, return...
445    if((htons(dhdr->param) & 0xf) != 0) {
446        return(0);
447    }
448
449    // If there isn't exactly 1 question, return...
450    if(htons(dhdr->num_questions) != 1) {
451        return(0);
452    }
453
454    /* At this point we can assume that the received packet format
455     * is ok.  Now we need to parse the packet for the "question"...
456     */
457
458    /* Set 'pp' to point to the start of the question list.
459     */
460    pp = (char *)dhdr->question;
461    l1 = *pp;
462    while(*pp) {
463        ql += *pp;
464        ql++;
465        pp += (*pp + 1);
466    }
467
468    /* If the name in the question matches our hostname, then send a
469     * reply...
470     *
471     * Referring to top of pg 20 of the document
472     *  http://files.multicastdns.org/draft-cheshire-dnsext-multicastdns.txt...
473     *
474     * Multicast DNS responses MUST be sent to UDP port 5353 on the
475     * 224.0.0.251 multicast address.
476     */
477    if((l1 == strlen(myname)) &&
478            (memcmp(myname,(char *)&dhdr->question[1],l1) == 0)) {
479        struct ip *ti, *ri;
480        struct Udphdr *tu, *ru;
481        struct ether_header *te;
482        struct  dnshdr *td;
483        short   type, class;
484        long    ttl;
485        struct  elapsed_tmr tmr;
486
487        te = EtherCopy(ehdr);
488        ti = (struct ip *)(te + 1);
489        ri = (struct ip *)(ehdr + 1);
490        ti->ip_vhl = ri->ip_vhl;
491        ti->ip_tos = ri->ip_tos;
492        ti->ip_id = ri->ip_id;
493        ti->ip_off = ri->ip_off;
494        ti->ip_ttl = UDP_TTL;
495        ti->ip_p = IP_UDP;
496        memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr,
497               sizeof(struct in_addr));
498        memcpy((char *)&(ti->ip_dst.s_addr),(char *)mDNSIp,
499               sizeof(struct in_addr));
500
501        tu = (struct Udphdr *)(ti + 1);
502        ru = (struct Udphdr *)(ri + 1);
503        tu->uh_sport = ru->uh_dport;
504        tu->uh_dport = htons(DNSMCAST_PORT);
505
506        td = (struct dnshdr *)(tu+1);
507
508        /* Flags: */
509        td->id = dhdr->id;
510        td->param = htons(0x8400);
511        td->num_questions = 0;
512        td->num_answers = htons(1);
513        td->num_authority = 0;
514        td->num_additional = 0;
515
516        /* Answers: */
517        pp = (char *)td->question;
518        memcpy(pp,(char *)dhdr->question,ql+1);
519        pp += (ql+1);
520
521        type = htons(TYPE_A);
522        memcpy(pp,(char *)&type,2);
523        pp += 2;
524
525        class = htons(CLASS_IN);
526        memcpy(pp,(char *)&class,2);
527        pp += 2;
528
529        ttl = htonl(900);
530        memcpy(pp,(char *)&ttl,4);
531        pp += 4;
532
533        *pp++ = 0;  /* 2-byte length of address */
534        *pp++ = 4;
535        memcpy(pp,(char *)BinIpAddr,4);
536
537        tu->uh_ulen = ecs((UDPSIZE + 27 + ql));
538        ti->ip_len = ecs((UDPSIZE + 27 + ql + sizeof(struct ip)));
539
540        ipChksum(ti);       /* Compute checksum of ip hdr */
541        udpChksum(ti);      /* Compute UDP checksum */
542
543        /* Delay for some random time between 20-120msec...
544         */
545        startElapsedTimer(&tmr,20 + (BinEnetAddr[5] & 0x3f));
546        while(!msecElapsed(&tmr));
547
548        sendBuffer(ETHERSIZE + IPSIZE + UDPSIZE + 27 + ql);
549    }
550    return(0);
551}
552
553/* DNS Cache utilities:
554 */
555void
556dnsCacheInit(void)
557{
558    int i;
559
560    for(i=0; i<MAX_CACHED_HOSTNAMES; i++) {
561        hostnames[i].idx = 0;
562        hostnames[i].addr = 0;
563        hostnames[i].name[0] = 0;
564    }
565    dnsCacheInitialized = 1;
566}
567
568int
569dnsCacheDump(void)
570{
571    int i, tot;
572    struct  dnscache *hnp;
573
574    tot = 0;
575    hnp = hostnames;
576    for(i=0; i<MAX_CACHED_HOSTNAMES; i++,hnp++) {
577        if(hnp->addr) {
578            printf("%3d %30s: %d.%d.%d.%d\n",hnp->idx,hnp->name, IP1(hnp->addr),
579                   IP2(hnp->addr), IP3(hnp->addr), IP4(hnp->addr));
580            tot++;
581        }
582    }
583    return(tot);
584}
585
586int
587dnsCacheAdd(char *name, unsigned long inaddr)
588{
589    int i, li, lowest;
590    struct  dnscache *hnp;
591    static  int idx = 0;
592
593    if(!dnsCacheInitialized) {
594        dnsCacheInit();
595    }
596
597    /* Validate incoming name size:
598     */
599    if((strlen(name) >= MAX_HOSTNAME_SIZE) || (inaddr == 0)) {
600        return(-1);
601    }
602
603    lowest = 0x70000000;
604
605    /* First look for an empty slot...
606     */
607    hnp = hostnames;
608    li = MAX_CACHED_HOSTNAMES;
609    for(i=0; i<MAX_CACHED_HOSTNAMES; i++,hnp++) {
610        if(hnp->addr == 0) {
611            strcpy(hnp->name,name);
612            hnp->addr = inaddr;
613            hnp->idx = idx++;
614            return(1);
615        } else {
616            if(hnp->idx < lowest) {
617                lowest = hnp->idx;
618                li = i;
619            }
620        }
621    }
622
623    if(i == MAX_CACHED_HOSTNAMES) {
624        return(-1);
625    }
626
627    /* If all slots are filled, use the slot that had the
628     * the lowest idx value (this would be the oldest entry)...
629     */
630    hnp = &hostnames[li];
631    strcpy(hnp->name,name);
632    hnp->addr = inaddr;
633    hnp->idx = idx++;
634    return(1);
635}
636
637int
638dnsCacheDelAddr(unsigned long addr)
639{
640    int i;
641
642    if(!dnsCacheInitialized) {
643        dnsCacheInit();
644        return(0);
645    }
646
647    for(i=0; i<MAX_CACHED_HOSTNAMES; i++) {
648        if(hostnames[i].addr == addr) {
649            hostnames[i].name[0] = 0;
650            hostnames[i].addr = 0;
651            return(1);
652        }
653    }
654    return(0);
655}
656
657int
658dnsCacheDelName(char *name)
659{
660    int i;
661
662    if(!dnsCacheInitialized) {
663        dnsCacheInit();
664        return(0);
665    }
666
667    for(i=0; i<MAX_CACHED_HOSTNAMES; i++) {
668        if(strcmp(hostnames[i].name,name) == 0) {
669            hostnames[i].name[0] = 0;
670            hostnames[i].addr = 0;
671            return(1);
672        }
673    }
674    return(0);
675}
676
677struct dnserr dnsErrTbl[] = {
678    { DNSERR_NOSRVR,            "no dns server" },
679    { DNSERR_SOCKETFAIL,        "socket fail" },
680    { DNSERR_FORMATERR,         "format error" },
681    { DNSERR_SRVRFAILURE,       "server error" },
682    { DNSERR_NAMENOEXIST,       "no name exists" },
683    { DNSERR_BADRESPTYPE,       "bad dns server response" },
684    { DNSERR_BADQSTNCOUNT,      "bad question count" },
685    { DNSERR_BADANSWRCOUNT,     "bad answer count" },
686    { DNSERR_NOTARESPONSE,      "replay not a dns response" },
687    { DNSERR_BADRESPID,         "bad dns response id" },
688
689    /* Must be last entry in table: */
690    { DNSERR_NULL,              "no error" }
691};
692
693char *
694dnsErrStr(int errno)
695{
696    struct  dnserr *dep;
697
698    dep = dnsErrTbl;
699    while(dep->errno != DNSERR_NULL) {
700        if(dep->errno == errno) {
701            return(dep->errstr);
702        }
703        dep++;
704    }
705    return("invalid dns errno");
706}
707
708char *DnsHelp[] = {
709    "DNS Client",
710    "{hostname} | {cmd args}",
711    " Valid cmd values:",
712    "  add   {name} {ip}",
713    "  cache {dump | init}",
714    "  mdns {on | off}",
715    "  del   {name}",
716    0,
717};
718
719int
720DnsCmd(int argc, char *argv[])
721{
722    unsigned long addr;
723
724    if(argc == 2) {
725        if((addr = getHostAddr(argv[1])) != 0) {
726            printf("%s: %d.%d.%d.%d\n",argv[1],
727                   IP1(dnsIP),IP2(dnsIP),IP3(dnsIP), IP4(dnsIP));
728        }
729    } else if(argc == 3) {
730        if(strcmp(argv[1],"cache") == 0) {
731            if(strcmp(argv[2],"dump") == 0) {
732                dnsCacheDump();
733            } else if(strcmp(argv[2],"init") == 0) {
734                dnsCacheInit();
735            } else {
736                return(CMD_PARAM_ERROR);
737            }
738        } else if(strcmp(argv[1],"mdns") == 0) {
739            extern void enableMulticastReception(void);
740            extern void disableMulticastReception(void);
741
742            if(strcmp(argv[2],"on") == 0) {
743                enableMulticastReception();
744            } else if(strcmp(argv[2],"off") == 0) {
745                disableMulticastReception();
746            } else {
747                return(CMD_PARAM_ERROR);
748            }
749        } else if(strcmp(argv[1],"del") == 0) {
750            dnsCacheDelName(argv[2]);
751        } else {
752            return(CMD_PARAM_ERROR);
753        }
754    } else if(argc == 4) {
755        if(strcmp(argv[1],"add") == 0) {
756            if(IpToBin(argv[3],(uchar *)&addr) < 0) {
757                return(CMD_FAILURE);
758            }
759            dnsCacheAdd(argv[2],addr);
760        } else {
761            return(CMD_PARAM_ERROR);
762        }
763    } else {
764        return(CMD_PARAM_ERROR);
765    }
766
767    return(CMD_SUCCESS);
768}
769
770#endif
Note: See TracBrowser for help on using the repository browser.