source: rtems-libbsd/dhcpcd/if-bsd.c @ 95fe5b1

55-freebsd-126-freebsd-12
Last change on this file since 95fe5b1 was f2ed769, checked in by Sebastian Huber <sebastian.huber@…>, on 01/30/14 at 12:29:46

DHCPCD(8): Import

Import DHCPCD(8) from:

http://roy.marples.name/projects/dhcpcd/

The upstream sources can be obtained via:

fossil clone http://roy.marples.name/projects/dhcpcd

The imported version is 2014-01-29 19:46:44 [6b209507bb].

  • Property mode set to 100644
File size: 17.5 KB
Line 
1/*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
4 * All rights reserved
5
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/ioctl.h>
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <sys/stat.h>
32#include <sys/sysctl.h>
33#include <sys/types.h>
34
35#include <arpa/inet.h>
36#include <net/if.h>
37#include <net/if_dl.h>
38#ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
39#  include <net/if_var.h>
40#endif
41#include <net/if_media.h>
42#include <net/route.h>
43#include <netinet/in.h>
44#include <netinet6/in6_var.h>
45#ifdef __DragonFly__
46#  include <netproto/802_11/ieee80211_ioctl.h>
47#elif __APPLE__
48  /* FIXME: Add apple includes so we can work out SSID */
49#else
50#  include <net80211/ieee80211_ioctl.h>
51#endif
52
53#include <errno.h>
54#include <fnmatch.h>
55#include <stddef.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59#include <syslog.h>
60#include <unistd.h>
61
62#include "config.h"
63#include "common.h"
64#include "dhcp.h"
65#include "if-options.h"
66#include "ipv4.h"
67#include "ipv6.h"
68
69#ifndef RT_ROUNDUP
70#define RT_ROUNDUP(a)                                                         \
71        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
72#define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
73#endif
74
75#define COPYOUT(sin, sa)                                                      \
76        sin.s_addr = ((sa) != NULL) ?                                         \
77            (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0
78
79#define COPYOUT6(sin, sa)                                                     \
80        sin.s6_addr = ((sa) != NULL) ?                                        \
81            (((struct sockaddr_in6 *)(void *)sa)->sin6_addr).s6_addr : 0
82
83#ifndef CLLADDR
84#  define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
85#endif
86
87static int r_fd = -1;
88static char *link_buf;
89static ssize_t link_buflen;
90
91int
92if_init(__unused struct interface *iface)
93{
94        /* BSD promotes secondary address by default */
95        return 0;
96}
97
98int
99if_conf(__unused struct interface *iface)
100{
101        /* No extra checks needed on BSD */
102        return 0;
103}
104
105#ifdef DEBUG_MEMORY
106static void
107cleanup(void)
108{
109
110        free(link_buf);
111}
112#endif
113
114int
115open_sockets(void)
116{
117        if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
118                return -1;
119        set_cloexec(socket_afnet);
120        if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
121                return -1;
122        set_cloexec(r_fd);
123        return 0;
124}
125
126int
127open_link_socket(void)
128{
129        int fd;
130
131#ifdef DEBUG_MEMORY
132        if (link_buf == NULL)
133                atexit(cleanup);
134#endif
135
136        fd = socket(PF_ROUTE, SOCK_RAW, 0);
137        if (fd != -1) {
138                set_cloexec(fd);
139                set_nonblock(fd);
140        }
141        return fd;
142}
143
144int
145getifssid(const char *ifname, char *ssid)
146{
147        int retval = -1;
148#if defined(SIOCG80211NWID)
149        struct ifreq ifr;
150        struct ieee80211_nwid nwid;
151#elif defined(IEEE80211_IOC_SSID)
152        struct ieee80211req ireq;
153        char nwid[IEEE80211_NWID_LEN + 1];
154#endif
155
156#if defined(SIOCG80211NWID) /* NetBSD */
157        memset(&ifr, 0, sizeof(ifr));
158        strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
159        memset(&nwid, 0, sizeof(nwid));
160        ifr.ifr_data = (void *)&nwid;
161        if (ioctl(socket_afnet, SIOCG80211NWID, &ifr) == 0) {
162                retval = nwid.i_len;
163                if (ssid) {
164                        memcpy(ssid, nwid.i_nwid, nwid.i_len);
165                        ssid[nwid.i_len] = '\0';
166                }
167        }
168#elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
169        memset(&ireq, 0, sizeof(ireq));
170        strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
171        ireq.i_type = IEEE80211_IOC_SSID;
172        ireq.i_val = -1;
173        memset(nwid, 0, sizeof(nwid));
174        ireq.i_data = &nwid;
175        if (ioctl(socket_afnet, SIOCG80211, &ireq) == 0) {
176                retval = ireq.i_len;
177                if (ssid) {
178                        memcpy(ssid, nwid, ireq.i_len);
179                        ssid[ireq.i_len] = '\0';
180                }
181        }
182#endif
183        return retval;
184}
185
186/*
187 * FreeBSD allows for Virtual Access Points
188 * We need to check if the interface is a Virtual Interface Master
189 * and if so, don't use it.
190 * This check is made by virtue of being a IEEE80211 device but
191 * returning the SSID gives an error.
192 */
193int
194if_vimaster(const char *ifname)
195{
196        struct ifmediareq ifmr;
197
198        memset(&ifmr, 0, sizeof(ifmr));
199        strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
200        if (ioctl(socket_afnet, SIOCGIFMEDIA, &ifmr) == -1)
201                return -1;
202        if (ifmr.ifm_status & IFM_AVALID &&
203            IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211)
204        {
205                if (getifssid(ifname, NULL) == -1)
206                        return 1;
207        }
208        return 0;
209}
210
211#ifdef INET
212int
213if_address(const struct interface *iface, const struct in_addr *address,
214    const struct in_addr *netmask, const struct in_addr *broadcast,
215    int action)
216{
217        struct ifaliasreq ifa;
218        union {
219                struct sockaddr *sa;
220                struct sockaddr_in *sin;
221        } _s;
222
223        memset(&ifa, 0, sizeof(ifa));
224        strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));
225
226#define ADDADDR(_var, _addr) {                                                \
227                _s.sa = &_var;                                                \
228                _s.sin->sin_family = AF_INET;                                 \
229                _s.sin->sin_len = sizeof(*_s.sin);                            \
230                memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
231        }
232
233        ADDADDR(ifa.ifra_addr, address);
234        ADDADDR(ifa.ifra_mask, netmask);
235        if (action >= 0 && broadcast) {
236                ADDADDR(ifa.ifra_broadaddr, broadcast);
237        }
238#undef ADDADDR
239
240        return ioctl(socket_afnet,
241            action < 0 ? SIOCDIFADDR :
242            action == 2 ? SIOCSIFADDR :  SIOCAIFADDR, &ifa);
243}
244
245int
246if_route(const struct rt *rt, int action)
247{
248        const struct dhcp_state *state;
249        union sockunion {
250                struct sockaddr sa;
251                struct sockaddr_in sin;
252                struct sockaddr_dl sdl;
253                struct sockaddr_storage ss;
254        } su;
255        struct rtm
256        {
257                struct rt_msghdr hdr;
258                char buffer[sizeof(su) * 4];
259        } rtm;
260        char *bp = rtm.buffer;
261        size_t l;
262        int retval = 0;
263
264#define ADDSU {                                                               \
265                l = RT_ROUNDUP(su.sa.sa_len);                                 \
266                memcpy(bp, &su, l);                                           \
267                bp += l;                                                      \
268        }
269#define ADDADDR(addr) {                                                       \
270                memset(&su, 0, sizeof(su));                                   \
271                su.sin.sin_family = AF_INET;                                  \
272                su.sin.sin_len = sizeof(su.sin);                              \
273                (&su.sin)->sin_addr = *addr;                                  \
274                ADDSU;                                                        \
275        }
276
277        state = D_CSTATE(rt->iface);
278        memset(&rtm, 0, sizeof(rtm));
279        rtm.hdr.rtm_version = RTM_VERSION;
280        rtm.hdr.rtm_seq = 1;
281        if (action == 0)
282                rtm.hdr.rtm_type = RTM_CHANGE;
283        else if (action > 0)
284                rtm.hdr.rtm_type = RTM_ADD;
285        else
286                rtm.hdr.rtm_type = RTM_DELETE;
287        rtm.hdr.rtm_flags = RTF_UP;
288        /* None interface subnet routes are static. */
289        if (rt->gate.s_addr != INADDR_ANY ||
290            rt->net.s_addr != state->net.s_addr ||
291            rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
292                rtm.hdr.rtm_flags |= RTF_STATIC;
293        rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
294        if (rt->dest.s_addr == rt->gate.s_addr &&
295            rt->net.s_addr == INADDR_BROADCAST)
296                rtm.hdr.rtm_flags |= RTF_HOST;
297        else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
298            rt->net.s_addr == INADDR_BROADCAST)
299                rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
300        else {
301                rtm.hdr.rtm_addrs |= RTA_NETMASK;
302                if (rtm.hdr.rtm_flags & RTF_STATIC)
303                        rtm.hdr.rtm_flags |= RTF_GATEWAY;
304                if (action >= 0)
305                        rtm.hdr.rtm_addrs |= RTA_IFA;
306        }
307
308        ADDADDR(&rt->dest);
309        if ((rtm.hdr.rtm_flags & RTF_HOST &&
310            rt->gate.s_addr != htonl(INADDR_LOOPBACK)) ||
311            !(rtm.hdr.rtm_flags & RTF_STATIC))
312        {
313                /* Make us a link layer socket for the host gateway */
314                memset(&su, 0, sizeof(su));
315                su.sdl.sdl_len = sizeof(struct sockaddr_dl);
316                link_addr(rt->iface->name, &su.sdl);
317                ADDSU;
318        } else
319                ADDADDR(&rt->gate);
320
321        if (rtm.hdr.rtm_addrs & RTA_NETMASK)
322                ADDADDR(&rt->net);
323
324        if (rtm.hdr.rtm_addrs & RTA_IFP) {
325                /* Make us a link layer socket for the host gateway */
326                memset(&su, 0, sizeof(su));
327                su.sdl.sdl_len = sizeof(struct sockaddr_dl);
328                link_addr(rt->iface->name, &su.sdl);
329                ADDSU;
330        }
331
332        if (rtm.hdr.rtm_addrs & RTA_IFA)
333                ADDADDR(&state->addr);
334
335#undef ADDADDR
336#undef ADDSU
337
338        rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
339        if (write(r_fd, &rtm, l) == -1)
340                retval = -1;
341        return retval;
342}
343#endif
344
345#ifdef INET6
346int
347if_address6(const struct ipv6_addr *a, int action)
348{
349        int s, r;
350        struct in6_aliasreq ifa;
351        struct in6_addr mask;
352
353        s = socket(AF_INET6, SOCK_DGRAM, 0);
354        if (s == -1)
355                return -1;
356        memset(&ifa, 0, sizeof(ifa));
357        strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name));
358        /*
359         * We should not set IN6_IFF_TENTATIVE as the kernel should be
360         * able to work out if it's a new address or not.
361         *
362         * We should set IN6_IFF_AUTOCONF, but the kernel won't let us.
363         * This is probably a safety measure, but still it's not entirely right
364         * either.
365         */
366#if 0
367        if (a->autoconf)
368                ifa.ifra_flags |= IN6_IFF_AUTOCONF;
369#endif
370
371#define ADDADDR(v, addr) {                                                    \
372                (v)->sin6_family = AF_INET6;                                  \
373                (v)->sin6_len = sizeof(*v);                                   \
374                (v)->sin6_addr = *addr;                                       \
375        }
376
377        ADDADDR(&ifa.ifra_addr, &a->addr);
378        ipv6_mask(&mask, a->prefix_len);
379        ADDADDR(&ifa.ifra_prefixmask, &mask);
380        ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime;
381        ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime;
382#undef ADDADDR
383
384        r = ioctl(s, action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
385        close(s);
386        return r;
387}
388
389int
390if_route6(const struct rt6 *rt, int action)
391{
392        union sockunion {
393                struct sockaddr sa;
394                struct sockaddr_in6 sin;
395                struct sockaddr_dl sdl;
396                struct sockaddr_storage ss;
397        } su;
398        struct rtm
399        {
400                struct rt_msghdr hdr;
401                char buffer[sizeof(su) * 4];
402        } rtm;
403        char *bp = rtm.buffer;
404        size_t l;
405        int retval = 0;
406        const struct ipv6_addr_l *lla;
407
408/* KAME based systems want to store the scope inside the sin6_addr
409 * for link local addreses */
410#ifdef __KAME__
411#define SCOPE {                                                               \
412                if (IN6_IS_ADDR_LINKLOCAL(&su.sin.sin6_addr)) {               \
413                        uint16_t scope = htons(su.sin.sin6_scope_id);         \
414                        memcpy(&su.sin.sin6_addr.s6_addr[2], &scope,          \
415                            sizeof(scope));                                   \
416                        su.sin.sin6_scope_id = 0;                             \
417                }                                                             \
418        }
419#else
420#define SCOPE
421#endif
422
423#define ADDSU {                                                               \
424                l = RT_ROUNDUP(su.sa.sa_len);                                 \
425                memcpy(bp, &su, l);                                           \
426                bp += l;                                                      \
427        }
428#define ADDADDRS(addr, scope) {                                               \
429                memset(&su, 0, sizeof(su));                                   \
430                su.sin.sin6_family = AF_INET6;                                \
431                su.sin.sin6_len = sizeof(su.sin);                             \
432                (&su.sin)->sin6_addr = *addr;                                 \
433                su.sin.sin6_scope_id = scope;                                 \
434                SCOPE;                                                        \
435                ADDSU;                                                        \
436        }
437#define ADDADDR(addr) ADDADDRS(addr, 0)
438
439        memset(&rtm, 0, sizeof(rtm));
440        rtm.hdr.rtm_version = RTM_VERSION;
441        rtm.hdr.rtm_seq = 1;
442        if (action == 0)
443                rtm.hdr.rtm_type = RTM_CHANGE;
444        else if (action > 0)
445                rtm.hdr.rtm_type = RTM_ADD;
446        else
447                rtm.hdr.rtm_type = RTM_DELETE;
448
449        rtm.hdr.rtm_flags = RTF_UP;
450        /* None interface subnet routes are static. */
451        if (IN6_IS_ADDR_UNSPECIFIED(&rt->dest) &&
452            IN6_IS_ADDR_UNSPECIFIED(&rt->net))
453                rtm.hdr.rtm_flags |= RTF_GATEWAY;
454#ifdef RTF_CLONING
455        else
456                rtm.hdr.rtm_flags |= RTF_CLONING;
457#endif
458
459        rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
460        if (action >= 0)
461                rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
462
463        ADDADDR(&rt->dest);
464        if (!(rtm.hdr.rtm_flags & RTF_GATEWAY)) {
465                lla = ipv6_linklocal(rt->iface);
466                if (lla == NULL) /* unlikely as we need a LL to get here */
467                        return -1;
468                ADDADDRS(&lla->addr, rt->iface->index);
469        } else {
470                lla = NULL;
471                ADDADDRS(&rt->gate, rt->iface->index);
472        }
473
474        if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
475                if (rtm.hdr.rtm_flags & RTF_GATEWAY) {
476                        memset(&su, 0, sizeof(su));
477                        su.sin.sin6_family = AF_INET6;
478                        ADDSU;
479                } else
480                        ADDADDR(&rt->net);
481        }
482
483        if (rtm.hdr.rtm_addrs & RTA_IFP) {
484                /* Make us a link layer socket for the host gateway */
485                memset(&su, 0, sizeof(su));
486                su.sdl.sdl_len = sizeof(struct sockaddr_dl);
487                link_addr(rt->iface->name, &su.sdl);
488                ADDSU;
489        }
490
491        if (rtm.hdr.rtm_addrs & RTA_IFA) {
492                if (lla == NULL) {
493                        lla = ipv6_linklocal(rt->iface);
494                        if (lla == NULL) /* unlikely */
495                                return -1;
496                }
497                ADDADDRS(&lla->addr, rt->iface->index);
498        }
499
500#undef ADDADDR
501#undef ADDSU
502#undef SCOPE
503
504        if (action >= 0 && rt->mtu) {
505                rtm.hdr.rtm_inits |= RTV_MTU;
506                rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
507        }
508
509        rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
510        if (write(r_fd, &rtm, l) == -1)
511                retval = -1;
512        return retval;
513}
514#endif
515
516static void
517get_addrs(int type, char *cp, struct sockaddr **sa)
518{
519        int i;
520
521        for (i = 0; i < RTAX_MAX; i++) {
522                if (type & (1 << i)) {
523                        sa[i] = (struct sockaddr *)cp;
524#ifdef DEBUG
525                        printf ("got %d %d %s\n", i, sa[i]->sa_family,
526                            inet_ntoa(((struct sockaddr_in *)sa[i])->
527                                sin_addr));
528#endif
529                        RT_ADVANCE(cp, sa[i]);
530                } else
531                        sa[i] = NULL;
532        }
533}
534
535#ifdef INET6
536int
537in6_addr_flags(const char *ifname, const struct in6_addr *addr)
538{
539        int s, flags;
540        struct in6_ifreq ifr6;
541
542        s = socket(AF_INET6, SOCK_DGRAM, 0);
543        flags = -1;
544        if (s != -1) {
545                memset(&ifr6, 0, sizeof(ifr6));
546                strncpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
547                ifr6.ifr_addr.sin6_family = AF_INET6;
548                ifr6.ifr_addr.sin6_addr = *addr;
549                if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1)
550                        flags = ifr6.ifr_ifru.ifru_flags6;
551                close(s);
552        }
553        return flags;
554}
555#endif
556
557int
558manage_link(int fd)
559{
560        char *p, *e, *cp;
561        char ifname[IF_NAMESIZE];
562        ssize_t bytes;
563        struct rt_msghdr *rtm;
564        struct if_announcemsghdr *ifan;
565        struct if_msghdr *ifm;
566        struct ifa_msghdr *ifam;
567        struct sockaddr *sa, *rti_info[RTAX_MAX];
568        int len;
569        struct sockaddr_dl sdl;
570#ifdef INET
571        struct rt rt;
572#endif
573#if defined(INET6) && !defined(LISTEN_DAD)
574        struct in6_addr ia6;
575        struct sockaddr_in6 *sin6;
576        int ifa_flags;
577#endif
578
579        for (;;) {
580                if (ioctl(fd, FIONREAD, &len) == -1)
581                        return -1;
582                if (link_buflen < len) {
583                        p = realloc(link_buf, len);
584                        if (p == NULL)
585                                return -1;
586                        link_buf = p;
587                        link_buflen = len;
588                }
589                bytes = read(fd, link_buf, link_buflen);
590                if (bytes == -1) {
591                        if (errno == EAGAIN)
592                                return 0;
593                        if (errno == EINTR)
594                                continue;
595                        return -1;
596                }
597                e = link_buf + bytes;
598                for (p = link_buf; p < e; p += rtm->rtm_msglen) {
599                        rtm = (struct rt_msghdr *)(void *)p;
600                        // Ignore messages generated by us
601                        if (rtm->rtm_pid == getpid())
602                                break;
603                        switch(rtm->rtm_type) {
604#ifdef RTM_IFANNOUNCE
605                        case RTM_IFANNOUNCE:
606                                ifan = (struct if_announcemsghdr *)(void *)p;
607                                switch(ifan->ifan_what) {
608                                case IFAN_ARRIVAL:
609                                        handle_interface(1, ifan->ifan_name);
610                                        break;
611                                case IFAN_DEPARTURE:
612                                        handle_interface(-1, ifan->ifan_name);
613                                        break;
614                                }
615                                break;
616#endif
617                        case RTM_IFINFO:
618                                ifm = (struct if_msghdr *)(void *)p;
619                                memset(ifname, 0, sizeof(ifname));
620                                if (!(if_indextoname(ifm->ifm_index, ifname)))
621                                        break;
622                                switch (ifm->ifm_data.ifi_link_state) {
623                                case LINK_STATE_DOWN:
624                                        len = LINK_DOWN;
625                                        break;
626                                case LINK_STATE_UP:
627                                        len = LINK_UP;
628                                        break;
629                                default:
630                                        /* handle_carrier will re-load
631                                         * the interface flags and check for
632                                         * IFF_RUNNING as some drivers that
633                                         * don't handle link state also don't
634                                         * set IFF_RUNNING when this routing
635                                         * message is generated.
636                                         * As such, it is a race ...*/
637                                        len = LINK_UNKNOWN;
638                                        break;
639                                }
640                                handle_carrier(len, ifm->ifm_flags, ifname);
641                                break;
642                        case RTM_DELETE:
643                                if (~rtm->rtm_addrs &
644                                    (RTA_DST | RTA_GATEWAY | RTA_NETMASK))
645                                        break;
646                                cp = (char *)(void *)(rtm + 1);
647                                sa = (struct sockaddr *)(void *)cp;
648                                if (sa->sa_family != AF_INET)
649                                        break;
650#ifdef INET
651                                get_addrs(rtm->rtm_addrs, cp, rti_info);
652                                memset(&rt, 0, sizeof(rt));
653                                rt.iface = NULL;
654                                COPYOUT(rt.dest, rti_info[RTAX_DST]);
655                                COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
656                                COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
657                                ipv4_routedeleted(&rt);
658#endif
659                                break;
660#ifdef RTM_CHGADDR
661                        case RTM_CHGADDR:       /* FALLTHROUGH */
662#endif
663                        case RTM_DELADDR:       /* FALLTHROUGH */
664                        case RTM_NEWADDR:
665                                ifam = (struct ifa_msghdr *)(void *)p;
666                                if (!if_indextoname(ifam->ifam_index, ifname))
667                                        break;
668                                cp = (char *)(void *)(ifam + 1);
669                                get_addrs(ifam->ifam_addrs, cp, rti_info);
670                                if (rti_info[RTAX_IFA] == NULL)
671                                        break;
672                                switch (rti_info[RTAX_IFA]->sa_family) {
673                                case AF_LINK:
674#ifdef RTM_CHGADDR
675                                        if (rtm->rtm_type != RTM_CHGADDR)
676                                                break;
677#else
678                                        if (rtm->rtm_type != RTM_NEWADDR)
679                                                break;
680#endif
681                                        memcpy(&sdl, rti_info[RTAX_IFA],
682                                            rti_info[RTAX_IFA]->sa_len);
683                                        handle_hwaddr(ifname,
684                                            (const unsigned char*)CLLADDR(&sdl),
685                                            sdl.sdl_alen);
686                                        break;
687#ifdef INET
688                                case AF_INET:
689                                case 255: /* FIXME: Why 255? */
690                                        COPYOUT(rt.dest, rti_info[RTAX_IFA]);
691                                        COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
692                                        COPYOUT(rt.gate, rti_info[RTAX_BRD]);
693                                        ipv4_handleifa(rtm->rtm_type,
694                                            NULL, ifname,
695                                            &rt.dest, &rt.net, &rt.gate);
696                                        break;
697#endif
698#if defined(INET6) && !defined(LISTEN_DAD)
699                                case AF_INET6:
700                                        sin6 = (struct sockaddr_in6*)(void *)
701                                            rti_info[RTAX_IFA];
702                                        memcpy(ia6.s6_addr,
703                                            sin6->sin6_addr.s6_addr,
704                                            sizeof(ia6.s6_addr));
705                                        if (rtm->rtm_type == RTM_NEWADDR) {
706                                                ifa_flags = in6_addr_flags(
707                                                                ifname,
708                                                                &ia6);
709                                                if (ifa_flags == -1)
710                                                        break;
711                                        } else
712                                                ifa_flags = 0;
713                                        ipv6_handleifa(rtm->rtm_type, NULL,
714                                            ifname, &ia6, ifa_flags);
715                                        break;
716#endif
717                                }
718                                break;
719                        }
720                }
721        }
722}
Note: See TracBrowser for help on using the repository browser.