~ubuntu-branches/ubuntu/vivid/minissdpd/vivid

« back to all changes in this revision

Viewing changes to ifacewatch.c

  • Committer: Package Import Robot
  • Author(s): Thomas Goirand
  • Date: 2014-05-28 06:47:51 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20140528064751-nutklh6s3asbp1r2
Tags: 1.2.20130907-1
* New upstream release (Closes: #719612).
* Fixed typo in package description (Closes: #653027).
* Removed 0001-always-disable-link_ntoa.diff, let's see if that still
  works in FreeBSD.
* Switched to compat level 9 and bumped standards-version.
* VCS URLs now canonical.
* Using DPKG_EXPORT_BUILDFLAGS and hardening=+all.
* Removed the [ $VERBOSE ] cruft from init script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: ifacewatch.c,v 1.3 2012/01/20 22:08:07 nanard Exp $ */
 
1
/* $Id: ifacewatch.c,v 1.13 2012/05/21 17:13:11 nanard Exp $ */
2
2
/* MiniUPnP project
3
 
 * (c) 2011 Thomas Bernard
 
3
 * (c) 2011-2012 Thomas Bernard
4
4
 * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
5
5
 * This software is subject to the conditions detailed
6
6
 * in the LICENCE file provided within the distribution */
7
7
#include "config.h"
8
8
 
9
9
#include <stdlib.h>
 
10
#include <stdio.h>
10
11
#include <unistd.h>
11
12
#include <string.h>
12
13
#include <sys/types.h>
19
20
#include <linux/rtnetlink.h>
20
21
#else   /* __linux__ */
21
22
#include <net/route.h>
 
23
#ifdef AF_LINK
 
24
#include <net/if_dl.h>
22
25
#endif
 
26
#endif  /* __linux__ */
23
27
#include <syslog.h>
24
28
 
25
29
#include "openssdpsocket.h"
 
30
#include "upnputils.h"
 
31
 
 
32
#ifndef __linux__
 
33
#if defined(__OpenBSD__) || defined(__FreeBSD__)
 
34
#define SALIGN (sizeof(long) - 1)
 
35
#else
 
36
#define SALIGN (sizeof(int32_t) - 1)
 
37
#endif
 
38
#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
 
39
#endif
26
40
 
27
41
int
28
42
OpenAndConfInterfaceWatchSocket(void)
41
55
 * routing socket open per system. */
42
56
#endif
43
57
        if(s < 0) {
44
 
                syslog(LOG_ERR, "OpenAndConfInterfaceWatchSocket socket: %m");
 
58
                syslog(LOG_ERR, "%s socket: %m",
 
59
                       "OpenAndConfInterfaceWatchSocket");
45
60
                return -1;
46
61
        }
 
62
        if(!set_non_blocking(s)) {
 
63
                syslog(LOG_WARNING, "%s failed to set socket non blocking : %m",
 
64
                       "OpenAndConfInterfaceWatchSocket");
 
65
        }
47
66
#ifdef __linux__
48
67
        memset(&addr, 0, sizeof(addr));
49
68
        addr.nl_family = AF_NETLINK;
73
92
        struct msghdr hdr;
74
93
        struct nlmsghdr *nlhdr;
75
94
        struct ifaddrmsg *ifa;
 
95
        struct rtattr *rta;
 
96
        int ifa_len;
76
97
 
77
98
        iov.iov_base = buffer;
78
99
        iov.iov_len = sizeof(buffer);
90
111
        for(nlhdr = (struct nlmsghdr *)buffer;
91
112
                NLMSG_OK(nlhdr, len);
92
113
                nlhdr = NLMSG_NEXT(nlhdr, len)) {
93
 
                syslog(LOG_DEBUG, "nlmsg_type=%d", nlhdr->nlmsg_type);
 
114
                int is_del = 0;
 
115
                char address[48];
 
116
                char ifname[IFNAMSIZ];
 
117
                address[0] = '\0';
 
118
                ifname[0] = '\0';
94
119
                if(nlhdr->nlmsg_type == NLMSG_DONE)
95
120
                        break;
96
 
                if(nlhdr->nlmsg_type == RTM_NEWADDR) {
97
 
                        ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr);
98
 
                        syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR index=%d", ifa->ifa_index);
99
 
                        for(i = 0; i < n_if_addr; i++) {
100
 
                                if(ifa->ifa_index == if_nametoindex(if_addr[i])) {
101
 
                                        AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 0);
102
 
                                        break;
103
 
                                }
104
 
                        }
105
 
                } else if(nlhdr->nlmsg_type == RTM_DELADDR) {
106
 
                        ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr);
107
 
                        syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR index=%d", ifa->ifa_index);
108
 
                        for(i = 0; i < n_if_addr; i++) {
109
 
                                if(ifa->ifa_index == if_nametoindex(if_addr[i])) {
110
 
                                        AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 1);
111
 
                                        break;
112
 
                                }
113
 
                        }
 
121
                switch(nlhdr->nlmsg_type) {
 
122
                /* case RTM_NEWLINK: */
 
123
                /* case RTM_DELLINK: */
 
124
                case RTM_DELADDR:
 
125
                        is_del = 1;
 
126
                case RTM_NEWADDR:
 
127
                        /* http://linux-hacks.blogspot.fr/2009/01/sample-code-to-learn-netlink.html */
 
128
                        ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr);
 
129
                        rta = (struct rtattr *)IFA_RTA(ifa);
 
130
                        ifa_len = IFA_PAYLOAD(nlhdr);
 
131
                        syslog(LOG_DEBUG, "%s %s index=%d fam=%d prefixlen=%d flags=%d scope=%d",
 
132
                               "ProcessInterfaceWatchNotify", is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
 
133
                               ifa->ifa_index, ifa->ifa_family, ifa->ifa_prefixlen,
 
134
                               ifa->ifa_flags, ifa->ifa_scope);
 
135
                        for(;RTA_OK(rta, ifa_len); rta = RTA_NEXT(rta, ifa_len)) {
 
136
                                /*RTA_DATA(rta)*/
 
137
                                /*rta_type : IFA_ADDRESS, IFA_LOCAL, etc. */
 
138
                                char tmp[128];
 
139
                                memset(tmp, 0, sizeof(tmp));
 
140
                                switch(rta->rta_type) {
 
141
                                case IFA_ADDRESS:
 
142
                                case IFA_LOCAL:
 
143
                                case IFA_BROADCAST:
 
144
                                case IFA_ANYCAST:
 
145
                                        inet_ntop(ifa->ifa_family, RTA_DATA(rta), tmp, sizeof(tmp));
 
146
                                        if(rta->rta_type == IFA_ADDRESS)
 
147
                                                strncpy(address, tmp, sizeof(address));
 
148
                                        break;
 
149
                                case IFA_LABEL:
 
150
                                        strncpy(tmp, RTA_DATA(rta), sizeof(tmp));
 
151
                                        strncpy(ifname, tmp, sizeof(ifname));
 
152
                                        break;
 
153
                                case IFA_CACHEINFO:
 
154
                                        {
 
155
                                                struct ifa_cacheinfo *cache_info;
 
156
                                                cache_info = RTA_DATA(rta);
 
157
                                                snprintf(tmp, sizeof(tmp), "valid=%u prefered=%u",
 
158
                                                         cache_info->ifa_valid, cache_info->ifa_prefered);
 
159
                                        }
 
160
                                        break;
 
161
                                default:
 
162
                                        strncpy(tmp, "*unknown*", sizeof(tmp));
 
163
                                }
 
164
                                syslog(LOG_DEBUG, " rta_len=%d rta_type=%d '%s'", rta->rta_len, rta->rta_type, tmp);
 
165
                        }
 
166
                        syslog(LOG_INFO, "%s: %s/%d %s",
 
167
                               is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
 
168
                               address, ifa->ifa_prefixlen, ifname);
 
169
                        for(i = 0; i < n_if_addr; i++) {
 
170
                                if((0 == strcmp(address, if_addr[i])) ||
 
171
                                   (0 == strcmp(ifname, if_addr[i])) ||
 
172
                                   (ifa->ifa_index == if_nametoindex(if_addr[i]))) {
 
173
                                        if(ifa->ifa_family == AF_INET && address[0] != '\0')
 
174
                                                AddDropMulticastMembership(s_ssdp, address, 0, is_del);
 
175
                                        else if(ifa->ifa_family == AF_INET6)
 
176
                                                AddDropMulticastMembership(s_ssdp6, if_addr[i], 1, is_del);
 
177
                                        break;
 
178
                                }
 
179
                        }
 
180
                        break;
 
181
                default:
 
182
                        syslog(LOG_DEBUG, "unknown nlmsg_type=%d", nlhdr->nlmsg_type);
114
183
                }
115
184
        }
116
185
#else /* __linux__ */
117
186
        struct rt_msghdr * rtm;
118
187
        struct ifa_msghdr * ifam;
 
188
        int is_del = 0;
 
189
        char tmp[64];
 
190
        char * p;
 
191
        struct sockaddr * sa;
 
192
        int addr;
 
193
        char address[48];
 
194
        char ifname[IFNAMSIZ];
 
195
        int family = AF_UNSPEC;
 
196
        int prefixlen = 0;
 
197
 
 
198
        address[0] = '\0';
 
199
        ifname[0] = '\0';
119
200
 
120
201
        len = recv(s, buffer, sizeof(buffer), 0);
121
202
        if(len < 0) {
122
 
                syslog(LOG_ERR, "ProcessInterfaceWatchNotify recv: %m");
 
203
                syslog(LOG_ERR, "%s recv: %m", "ProcessInterfaceWatchNotify");
123
204
                return -1;
124
205
        }
125
206
        rtm = (struct rt_msghdr *)buffer;
126
207
        switch(rtm->rtm_type) {
 
208
        case RTM_DELADDR:
 
209
                is_del = 1;
127
210
        case RTM_NEWADDR:
128
211
                ifam = (struct ifa_msghdr *)buffer;
129
 
                syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR index=%d", ifam->ifam_index);
130
 
                for(i = 0; i < n_if_addr; i++) {
131
 
                        if(ifam->ifam_index == if_nametoindex(if_addr[i])) {
132
 
                                AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 0);
 
212
                syslog(LOG_DEBUG, "%s %s len=%d/%hu index=%hu addrs=%x flags=%x",
 
213
                       "ProcessInterfaceWatchNotify", is_del?"RTM_DELADDR":"RTM_NEWADDR",
 
214
                       (int)len, ifam->ifam_msglen,
 
215
                       ifam->ifam_index, ifam->ifam_addrs, ifam->ifam_flags);
 
216
                p = buffer + sizeof(struct ifa_msghdr);
 
217
                addr = 1;
 
218
                while(p < buffer + len) {
 
219
                        sa = (struct sockaddr *)p;
 
220
                        while(!(addr & ifam->ifam_addrs) && (addr <= ifam->ifam_addrs))
 
221
                                addr = addr << 1;
 
222
                        sockaddr_to_string(sa, tmp, sizeof(tmp));
 
223
                        syslog(LOG_DEBUG, " %s", tmp);
 
224
                        switch(addr) {
 
225
                        case RTA_DST:
 
226
                        case RTA_GATEWAY:
 
227
                                break;
 
228
                        case RTA_NETMASK:
 
229
                                if(sa->sa_family == AF_INET
 
230
#if defined(__OpenBSD__)
 
231
                                   || (sa->sa_family == 0 &&
 
232
                                       sa->sa_len <= sizeof(struct sockaddr_in))
 
233
#endif
 
234
                                   ) {
 
235
                                        uint32_t sin_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
 
236
                                        while((prefixlen < 32) &&
 
237
                                              ((sin_addr & (1 << (31 - prefixlen))) != 0))
 
238
                                                prefixlen++;
 
239
                                } else if(sa->sa_family == AF_INET6
 
240
#if defined(__OpenBSD__)
 
241
                                          || (sa->sa_family == 0 &&
 
242
                                              sa->sa_len == sizeof(struct sockaddr_in6))
 
243
#endif
 
244
                                          ) {
 
245
                                        int i = 0;
 
246
                                        uint8_t * q =  ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
 
247
                                        while((*q == 0xff) && (i < 16)) {
 
248
                                                prefixlen += 8;
 
249
                                                q++; i++;
 
250
                                        }
 
251
                                        if(i < 16) {
 
252
                                                i = 0;
 
253
                                                while((i < 8) &&
 
254
                                                      ((*q & (1 << (7 - i))) != 0))
 
255
                                                        i++;
 
256
                                                prefixlen += i;
 
257
                                        }
 
258
                                }
 
259
                                break;
 
260
                        case RTA_GENMASK:
 
261
                                break;
 
262
                        case RTA_IFP:
 
263
#ifdef AF_LINK
 
264
                                if(sa->sa_family == AF_LINK) {
 
265
                                        struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa;
 
266
                                        memset(ifname, 0, sizeof(ifname));
 
267
                                        memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
 
268
                                }
 
269
#endif
 
270
                                break;
 
271
                        case RTA_IFA:
 
272
                                family = sa->sa_family;
 
273
                                if(sa->sa_family == AF_INET) {
 
274
                                        inet_ntop(sa->sa_family,
 
275
                                                  &((struct sockaddr_in *)sa)->sin_addr,
 
276
                                                  address, sizeof(address));
 
277
                                } else if(sa->sa_family == AF_INET6) {
 
278
                                        inet_ntop(sa->sa_family,
 
279
                                                  &((struct sockaddr_in6 *)sa)->sin6_addr,
 
280
                                                  address, sizeof(address));
 
281
                                }
 
282
                                break;
 
283
                        case RTA_AUTHOR:
 
284
                                break;
 
285
                        case RTA_BRD:
133
286
                                break;
134
287
                        }
 
288
#if 0
 
289
                        syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x",
 
290
                               (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3],
 
291
                               (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3]); 
 
292
                        syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x",
 
293
                               (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7],
 
294
                               (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7]); 
 
295
#endif
 
296
                        p += SA_RLEN(sa);
 
297
                        addr = addr << 1;
135
298
                }
136
 
                break;
137
 
        case RTM_DELADDR:
138
 
                ifam = (struct ifa_msghdr *)buffer;
139
 
                syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR index=%d", ifam->ifam_index);
 
299
                syslog(LOG_INFO, "%s: %s/%d %s",
 
300
                       is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
 
301
                       address, prefixlen, ifname);
140
302
                for(i = 0; i < n_if_addr; i++) {
141
 
                        if(ifam->ifam_index == if_nametoindex(if_addr[i])) {
142
 
                                /* I dont think it is useful */
143
 
                                /*AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 1);*/
 
303
                        if(0 == strcmp(address, if_addr[i]) ||
 
304
                           0 == strcmp(ifname, if_addr[i]) ||
 
305
                           ifam->ifam_index == if_nametoindex(if_addr[i])) {
 
306
                                if(family == AF_INET && address[0] != '\0')
 
307
                                        AddDropMulticastMembership(s_ssdp, address, 0, is_del);
 
308
                                else if(family == AF_INET6)
 
309
                                        AddDropMulticastMembership(s_ssdp6, if_addr[i], 1, is_del);
144
310
                                break;
145
311
                        }
146
312
                }
147
313
                break;
148
314
        default:
149
 
                syslog(LOG_DEBUG, "rtm->rtm_type=%d", rtm->rtm_type);
 
315
                syslog(LOG_DEBUG, "Unknown RTM message : rtm->rtm_type=%d len=%d",
 
316
                       rtm->rtm_type, (int)len);
150
317
        }
151
318
#endif
152
319
        return 0;