source: rtems-libbsd/mDNSResponder/mDNSPosix/mDNSUNP.c @ d496d66

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since d496d66 was d496d66, checked in by Sebastian Huber <sebastian.huber@…>, on 11/04/14 at 10:56:59

mDNS: Avoid uninitialized memory

Use calloc() instead of malloc().

  • Property mode set to 100755
File size: 23.9 KB
Line 
1/* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "mDNSUNP.h"
19
20#include <errno.h>
21#include <assert.h>
22#include <string.h>
23#include <stdlib.h>
24#include <sys/uio.h>
25#include <sys/ioctl.h>
26#include <signal.h>
27#include <unistd.h>
28#include <stdio.h>
29
30/* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
31   macro, usually defined in <sys/param.h> or someplace like that, to make sure the
32   CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
33   should be set to the name of the header to include to get the ALIGN(P) macro.
34 */
35#ifdef NEED_ALIGN_MACRO
36#include NEED_ALIGN_MACRO
37#endif
38
39/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
40   other platforms don't even have that include file.  So,
41   if we haven't yet got a definition, let's try to find
42   <sys/sockio.h>.
43 */
44
45#ifndef SIOCGIFCONF
46    #include <sys/sockio.h>
47#endif
48
49/* sockaddr_dl is only referenced if we're using IP_RECVIF,
50   so only include the header in that case.
51 */
52
53#ifdef  IP_RECVIF
54    #include <net/if_dl.h>
55#endif
56
57#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
58#include <net/if_var.h>
59#include <netinet/in_var.h>
60// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
61#endif
62
63#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
64#include <netdb.h>
65#include <arpa/inet.h>
66
67/* Converts a prefix length to IPv6 network mask */
68void plen_to_mask(int plen, char *addr) {
69    int i;
70    int colons=7; /* Number of colons in IPv6 address */
71    int bits_in_block=16; /* Bits per IPv6 block */
72    for(i=0; i<=colons; i++) {
73        int block, ones=0xffff, ones_in_block;
74        if (plen>bits_in_block) ones_in_block=bits_in_block;
75        else ones_in_block=plen;
76        block = ones & (ones << (bits_in_block-ones_in_block));
77        i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
78        plen -= ones_in_block;
79    }
80}
81
82/* Gets IPv6 interface information from the /proc filesystem in linux*/
83struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
84{
85    struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
86    FILE *fp;
87    char addr[8][5];
88    int flags, myflags, index, plen, scope;
89    char ifname[9], lastname[IFNAMSIZ];
90    char addr6[32+7+1]; /* don't forget the seven ':' */
91    struct addrinfo hints, *res0;
92    struct sockaddr_in6 *sin6;
93    struct in6_addr *addrptr;
94    int err;
95    int sockfd = -1;
96    struct ifreq ifr;
97
98    res0=NULL;
99    ifihead = NULL;
100    ifipnext = &ifihead;
101    lastname[0] = 0;
102
103    if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
104        sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
105        if (sockfd < 0) {
106            goto gotError;
107        }
108        while (fscanf(fp,
109                      "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
110                      addr[0],addr[1],addr[2],addr[3],
111                      addr[4],addr[5],addr[6],addr[7],
112                      &index, &plen, &scope, &flags, ifname) != EOF) {
113
114            myflags = 0;
115            if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
116                if (doaliases == 0)
117                    continue;   /* already processed this interface */
118                myflags = IFI_ALIAS;
119            }
120            memcpy(lastname, ifname, IFNAMSIZ);
121            ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
122            if (ifi == NULL) {
123                goto gotError;
124            }
125
126            ifipold   = *ifipnext;       /* need this later */
127            ifiptr    = ifipnext;
128            *ifipnext = ifi;            /* prev points to this new one */
129            ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
130
131            sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
132                    addr[0],addr[1],addr[2],addr[3],
133                    addr[4],addr[5],addr[6],addr[7]);
134
135            /* Add address of the interface */
136            memset(&hints, 0, sizeof(hints));
137            hints.ai_family = AF_INET6;
138            hints.ai_flags = AI_NUMERICHOST;
139            err = getaddrinfo(addr6, NULL, &hints, &res0);
140            if (err) {
141                goto gotError;
142            }
143            ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
144            if (ifi->ifi_addr == NULL) {
145                goto gotError;
146            }
147            memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
148
149            /* Add netmask of the interface */
150            char ipv6addr[INET6_ADDRSTRLEN];
151            plen_to_mask(plen, ipv6addr);
152            ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
153            if (ifi->ifi_addr == NULL) {
154                goto gotError;
155            }
156            sin6=calloc(1, sizeof(struct sockaddr_in6));
157            addrptr=calloc(1, sizeof(struct in6_addr));
158            inet_pton(family, ipv6addr, addrptr);
159            sin6->sin6_family=family;
160            sin6->sin6_addr=*addrptr;
161            sin6->sin6_scope_id=scope;
162            memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
163            free(sin6);
164
165
166            /* Add interface name */
167            memcpy(ifi->ifi_name, ifname, IFI_NAME);
168
169            /* Add interface index */
170            ifi->ifi_index = index;
171
172            /* Add interface flags*/
173            memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
174            if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
175                if (errno == EADDRNOTAVAIL) {
176                    /*
177                     * If the main interface is configured with no IP address but
178                     * an alias interface exists with an IP address, you get
179                     * EADDRNOTAVAIL for the main interface
180                     */
181                    free(ifi->ifi_addr);
182                    free(ifi);
183                    ifipnext  = ifiptr;
184                    *ifipnext = ifipold;
185                    continue;
186                } else {
187                    goto gotError;
188                }
189            }
190            ifi->ifi_flags = ifr.ifr_flags;
191            freeaddrinfo(res0);
192            res0=NULL;
193        }
194    }
195    goto done;
196
197gotError:
198    if (ifihead != NULL) {
199        free_ifi_info(ifihead);
200        ifihead = NULL;
201    }
202    if (res0 != NULL) {
203        freeaddrinfo(res0);
204        res0=NULL;
205    }
206done:
207    if (sockfd != -1) {
208        assert(close(sockfd) == 0);
209    }
210    return(ifihead);    /* pointer to first structure in linked list */
211}
212#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
213
214struct ifi_info *get_ifi_info(int family, int doaliases)
215{
216    int junk;
217    struct ifi_info     *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
218    int sockfd, sockf6, len, lastlen, flags, myflags;
219#ifdef NOT_HAVE_IF_NAMETOINDEX
220    int index = 200;
221#endif
222    char                *ptr, *buf, lastname[IFNAMSIZ], *cptr;
223    struct ifconf ifc;
224    struct ifreq        *ifr, ifrcopy;
225    struct sockaddr_in  *sinptr;
226
227#if defined(AF_INET6) && HAVE_IPV6
228    struct sockaddr_in6 *sinptr6;
229#endif
230
231#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
232    if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
233#endif
234
235    sockfd = -1;
236    sockf6 = -1;
237    buf = NULL;
238    ifihead = NULL;
239
240    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
241    if (sockfd < 0) {
242        goto gotError;
243    }
244
245    lastlen = 0;
246    len = 100 * sizeof(struct ifreq);   /* initial buffer size guess */
247    for ( ; ; ) {
248        buf = (char*)calloc(1, len);
249        if (buf == NULL) {
250            goto gotError;
251        }
252        ifc.ifc_len = len;
253        ifc.ifc_buf = buf;
254        if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
255            if (errno != EINVAL || lastlen != 0) {
256                goto gotError;
257            }
258        } else {
259            if (ifc.ifc_len == lastlen)
260                break;      /* success, len has not changed */
261            lastlen = ifc.ifc_len;
262        }
263        len += 10 * sizeof(struct ifreq);   /* increment */
264        free(buf);
265    }
266    ifihead = NULL;
267    ifipnext = &ifihead;
268    lastname[0] = 0;
269/* end get_ifi_info1 */
270
271/* include get_ifi_info2 */
272    for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
273        ifr = (struct ifreq *) ptr;
274
275        /* Advance to next one in buffer */
276        if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
277            ptr += sizeof(struct ifreq);
278        else
279            ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
280
281//      fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
282
283        if (ifr->ifr_addr.sa_family != family)
284            continue;   /* ignore if not desired address family */
285
286        myflags = 0;
287        if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
288            *cptr = 0;      /* replace colon will null */
289        if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
290            if (doaliases == 0)
291                continue;   /* already processed this interface */
292            myflags = IFI_ALIAS;
293        }
294        memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
295
296        ifrcopy = *ifr;
297        if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
298            goto gotError;
299        }
300
301        flags = ifrcopy.ifr_flags;
302        if ((flags & IFF_UP) == 0)
303            continue;   /* ignore if interface not up */
304
305        ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
306        if (ifi == NULL) {
307            goto gotError;
308        }
309        ifipold   = *ifipnext;       /* need this later */
310        ifiptr    = ifipnext;
311        *ifipnext = ifi;             /* prev points to this new one */
312        ifipnext  = &ifi->ifi_next;  /* pointer to next one goes here */
313
314        ifi->ifi_flags = flags;     /* IFF_xxx values */
315        ifi->ifi_myflags = myflags; /* IFI_xxx values */
316#ifndef NOT_HAVE_IF_NAMETOINDEX
317        ifi->ifi_index = if_nametoindex(ifr->ifr_name);
318#else
319        ifrcopy = *ifr;
320#ifdef SIOCGIFINDEX
321        if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
322            ifi->ifi_index = ifrcopy.ifr_index;
323        else
324#endif
325        ifi->ifi_index = index++;       /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
326#endif
327        memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
328        ifi->ifi_name[IFI_NAME-1] = '\0';
329/* end get_ifi_info2 */
330/* include get_ifi_info3 */
331        switch (ifr->ifr_addr.sa_family) {
332        case AF_INET:
333            sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
334            if (ifi->ifi_addr == NULL) {
335                ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
336                if (ifi->ifi_addr == NULL) {
337                    goto gotError;
338                }
339                memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
340
341#ifdef  SIOCGIFNETMASK
342                if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
343                    if (errno == EADDRNOTAVAIL) {
344                        /*
345                         * If the main interface is configured with no IP address but
346                         * an alias interface exists with an IP address, you get
347                         * EADDRNOTAVAIL for the main interface
348                         */
349                        free(ifi->ifi_addr);
350                        free(ifi);
351                        ifipnext  = ifiptr;
352                        *ifipnext = ifipold;
353                        continue;
354                    } else {
355                        goto gotError;
356                    }
357                }
358
359                ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
360                if (ifi->ifi_netmask == NULL) goto gotError;
361                sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
362                /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
363#ifndef NOT_HAVE_SA_LEN
364                sinptr->sin_len    = sizeof(struct sockaddr_in);
365#endif
366                sinptr->sin_family = AF_INET;
367                memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
368#endif
369
370#ifdef  SIOCGIFBRDADDR
371                if (flags & IFF_BROADCAST) {
372                    if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
373                        goto gotError;
374                    }
375                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
376                    /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
377#ifndef NOT_HAVE_SA_LEN
378                    sinptr->sin_len    = sizeof( struct sockaddr_in );
379#endif
380                    sinptr->sin_family = AF_INET;
381                    ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
382                    if (ifi->ifi_brdaddr == NULL) {
383                        goto gotError;
384                    }
385                    memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
386                }
387#endif
388
389#ifdef  SIOCGIFDSTADDR
390                if (flags & IFF_POINTOPOINT) {
391                    if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) {
392                        goto gotError;
393                    }
394                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
395                    /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
396#ifndef NOT_HAVE_SA_LEN
397                    sinptr->sin_len    = sizeof( struct sockaddr_in );
398#endif
399                    sinptr->sin_family = AF_INET;
400                    ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
401                    if (ifi->ifi_dstaddr == NULL) {
402                        goto gotError;
403                    }
404                    memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
405                }
406#endif
407            }
408            break;
409
410#if defined(AF_INET6) && HAVE_IPV6
411        case AF_INET6:
412            sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
413            if (ifi->ifi_addr == NULL) {
414                ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
415                if (ifi->ifi_addr == NULL) {
416                    goto gotError;
417                }
418
419                /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
420                /* We need to strip that out */
421                if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
422                    sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
423                memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
424
425#ifdef  SIOCGIFNETMASK_IN6
426                {
427                    struct in6_ifreq ifr6;
428                    if (sockf6 == -1)
429                        sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
430                    memset(&ifr6, 0, sizeof(ifr6));
431                    memcpy(&ifr6.ifr_name,           &ifr->ifr_name, sizeof(ifr6.ifr_name          ));
432                    memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
433                    if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
434                        if (errno == EADDRNOTAVAIL) {
435                            /*
436                             * If the main interface is configured with no IP address but
437                             * an alias interface exists with an IP address, you get
438                             * EADDRNOTAVAIL for the main interface
439                             */
440                            free(ifi->ifi_addr);
441                            free(ifi);
442                            ifipnext  = ifiptr;
443                            *ifipnext = ifipold;
444                            continue;
445                        } else {
446                            goto gotError;
447                        }
448                    }
449                    ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
450                    if (ifi->ifi_netmask == NULL) goto gotError;
451                    sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
452                    memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
453                }
454#endif
455            }
456            break;
457#endif
458
459        default:
460            break;
461        }
462    }
463    goto done;
464
465gotError:
466    if (ifihead != NULL) {
467        free_ifi_info(ifihead);
468        ifihead = NULL;
469    }
470
471done:
472    if (buf != NULL) {
473        free(buf);
474    }
475    if (sockfd != -1) {
476        junk = close(sockfd);
477        assert(junk == 0);
478    }
479    if (sockf6 != -1) {
480        junk = close(sockf6);
481        assert(junk == 0);
482    }
483    return(ifihead);    /* pointer to first structure in linked list */
484}
485/* end get_ifi_info3 */
486
487/* include free_ifi_info */
488void
489free_ifi_info(struct ifi_info *ifihead)
490{
491    struct ifi_info *ifi, *ifinext;
492
493    for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
494        if (ifi->ifi_addr != NULL)
495            free(ifi->ifi_addr);
496        if (ifi->ifi_netmask != NULL)
497            free(ifi->ifi_netmask);
498        if (ifi->ifi_brdaddr != NULL)
499            free(ifi->ifi_brdaddr);
500        if (ifi->ifi_dstaddr != NULL)
501            free(ifi->ifi_dstaddr);
502        ifinext = ifi->ifi_next;    /* can't fetch ifi_next after free() */
503        free(ifi);                  /* the ifi_info{} itself */
504    }
505}
506/* end free_ifi_info */
507
508ssize_t
509recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
510               struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
511{
512    struct msghdr msg;
513    struct iovec iov[1];
514    ssize_t n;
515
516#ifdef CMSG_FIRSTHDR
517    struct cmsghdr  *cmptr;
518    union {
519        struct cmsghdr cm;
520        char control[1024];
521    } control_un;
522
523    *ttl = 255;         // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
524
525    msg.msg_control = control_un.control;
526    msg.msg_controllen = sizeof(control_un.control);
527    msg.msg_flags = 0;
528#else
529    memset(&msg, 0, sizeof(msg));   /* make certain msg_accrightslen = 0 */
530#endif /* CMSG_FIRSTHDR */
531
532    msg.msg_name = (char *) sa;
533    msg.msg_namelen = *salenptr;
534    iov[0].iov_base = (char *)ptr;
535    iov[0].iov_len = nbytes;
536    msg.msg_iov = iov;
537    msg.msg_iovlen = 1;
538
539    if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
540        return(n);
541
542    *salenptr = msg.msg_namelen;    /* pass back results */
543    if (pktp) {
544        /* 0.0.0.0, i/f = -1 */
545        /* We set the interface to -1 so that the caller can
546           tell whether we returned a meaningful value or
547           just some default.  Previously this code just
548           set the value to 0, but I'm concerned that 0
549           might be a valid interface value.
550         */
551        memset(pktp, 0, sizeof(struct my_in_pktinfo));
552        pktp->ipi_ifindex = -1;
553    }
554/* end recvfrom_flags1 */
555
556/* include recvfrom_flags2 */
557#ifndef CMSG_FIRSTHDR
558    #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
559    *flagsp = 0;                    /* pass back results */
560    return(n);
561#else
562
563    *flagsp = msg.msg_flags;        /* pass back results */
564    if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
565        (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
566        return(n);
567
568    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
569         cmptr = CMSG_NXTHDR(&msg, cmptr)) {
570
571#ifdef  IP_PKTINFO
572#if in_pktinfo_definition_is_missing
573        struct in_pktinfo
574        {
575            int ipi_ifindex;
576            struct in_addr ipi_spec_dst;
577            struct in_addr ipi_addr;
578        };
579#endif
580        if (cmptr->cmsg_level == IPPROTO_IP &&
581            cmptr->cmsg_type == IP_PKTINFO) {
582            struct in_pktinfo *tmp;
583            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
584
585            tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
586            sin->sin_family = AF_INET;
587            sin->sin_addr = tmp->ipi_addr;
588            sin->sin_port = 0;
589            pktp->ipi_ifindex = tmp->ipi_ifindex;
590            continue;
591        }
592#endif
593
594#ifdef  IP_RECVDSTADDR
595        if (cmptr->cmsg_level == IPPROTO_IP &&
596            cmptr->cmsg_type == IP_RECVDSTADDR) {
597            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
598
599            sin->sin_family = AF_INET;
600            sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
601            sin->sin_port = 0;
602            continue;
603        }
604#endif
605
606#ifdef  IP_RECVIF
607        if (cmptr->cmsg_level == IPPROTO_IP &&
608            cmptr->cmsg_type == IP_RECVIF) {
609            struct sockaddr_dl  *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
610#ifndef HAVE_BROKEN_RECVIF_NAME
611            int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
612            strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
613#endif
614            pktp->ipi_ifindex = sdl->sdl_index;
615#ifdef HAVE_BROKEN_RECVIF_NAME
616            if (sdl->sdl_index == 0) {
617                pktp->ipi_ifindex = *(uint_t*)sdl;
618            }
619#endif
620            assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
621            // null terminated because of memset above
622            continue;
623        }
624#endif
625
626#ifdef  IP_RECVTTL
627        if (cmptr->cmsg_level == IPPROTO_IP &&
628            cmptr->cmsg_type == IP_RECVTTL) {
629            *ttl = *(u_char*)CMSG_DATA(cmptr);
630            continue;
631        }
632        else if (cmptr->cmsg_level == IPPROTO_IP &&
633                 cmptr->cmsg_type == IP_TTL) {  // some implementations seem to send IP_TTL instead of IP_RECVTTL
634            *ttl = *(int*)CMSG_DATA(cmptr);
635            continue;
636        }
637#endif
638
639#if defined(IPV6_PKTINFO) && HAVE_IPV6
640        if (cmptr->cmsg_level == IPPROTO_IPV6 &&
641            cmptr->cmsg_type  == IPV6_2292_PKTINFO) {
642            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
643            struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
644
645            sin6->sin6_family   = AF_INET6;
646#ifndef NOT_HAVE_SA_LEN
647            sin6->sin6_len      = sizeof(*sin6);
648#endif
649            sin6->sin6_addr     = ip6_info->ipi6_addr;
650            sin6->sin6_flowinfo = 0;
651            sin6->sin6_scope_id = 0;
652            sin6->sin6_port     = 0;
653            pktp->ipi_ifindex   = ip6_info->ipi6_ifindex;
654            continue;
655        }
656#endif
657
658#if defined(IPV6_HOPLIMIT) && HAVE_IPV6
659        if (cmptr->cmsg_level == IPPROTO_IPV6 &&
660            cmptr->cmsg_type == IPV6_2292_HOPLIMIT) {
661            *ttl = *(int*)CMSG_DATA(cmptr);
662            continue;
663        }
664#endif
665        assert(0);  // unknown ancillary data
666    }
667    return(n);
668#endif /* CMSG_FIRSTHDR */
669}
670
671// **********************************************************************************************
672
673// daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
674// Returns 0 on success, -1 on failure.
675
676#ifdef NOT_HAVE_DAEMON
677#include <fcntl.h>
678#include <sys/stat.h>
679#include <sys/signal.h>
680
681int daemon(int nochdir, int noclose)
682{
683    switch (fork())
684    {
685    case -1: return (-1);       // Fork failed
686    case 0:  break;             // Child -- continue
687    default: _exit(0);          // Parent -- exit
688    }
689
690    if (setsid() == -1) return(-1);
691
692    signal(SIGHUP, SIG_IGN);
693
694    switch (fork())             // Fork again, primarily for reasons of Unix trivia
695    {
696    case -1: return (-1);       // Fork failed
697    case 0:  break;             // Child -- continue
698    default: _exit(0);          // Parent -- exit
699    }
700
701    if (!nochdir) (void)chdir("/");
702    umask(0);
703
704    if (!noclose)
705    {
706        int fd = open("/dev/null", O_RDWR, 0);
707        if (fd != -1)
708        {
709            // Avoid unnecessarily duplicating a file descriptor to itself
710            if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
711            if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
712            if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
713            if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
714                (void)close (fd);
715        }
716    }
717    return (0);
718}
719#endif /* NOT_HAVE_DAEMON */
Note: See TracBrowser for help on using the repository browser.