1 /*
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)in.c 8.4 (Berkeley) 01/09/95
8 */
9
10 #include <sys/param.h>
11 #include <sys/ioctl.h>
12 #include <sys/errno.h>
13 #include <sys/malloc.h>
14 #include <sys/socket.h>
15 #include <sys/socketvar.h>
16
17 #include <net/if.h>
18 #include <net/route.h>
19
20 #include <netinet/in_systm.h>
21 #include <netinet/in.h>
22 #include <netinet/in_var.h>
23 #include <netinet/if_ether.h>
24
25 #ifdef INET
26 /*
27 * Return the network number from an internet address.
28 */
29 u_long
in_netof(in)30 in_netof(in)
31 struct in_addr in;
32 {
33 register u_long i = ntohl(in.s_addr);
34 register u_long net;
35 register struct in_ifaddr *ia;
36
37 if (IN_CLASSA(i))
38 net = i & IN_CLASSA_NET;
39 else if (IN_CLASSB(i))
40 net = i & IN_CLASSB_NET;
41 else if (IN_CLASSC(i))
42 net = i & IN_CLASSC_NET;
43 else if (IN_CLASSD(i))
44 net = i & IN_CLASSD_NET;
45 else
46 return (0);
47
48 /*
49 * Check whether network is a subnet;
50 * if so, return subnet number.
51 */
52 for (ia = in_ifaddr; ia; ia = ia->ia_next)
53 if (net == ia->ia_net)
54 return (i & ia->ia_subnetmask);
55 return (net);
56 }
57
58 #ifndef SUBNETSARELOCAL
59 #define SUBNETSARELOCAL 1
60 #endif
61 int subnetsarelocal = SUBNETSARELOCAL;
62 /*
63 * Return 1 if an internet address is for a ``local'' host
64 * (one to which we have a connection). If subnetsarelocal
65 * is true, this includes other subnets of the local net.
66 * Otherwise, it includes only the directly-connected (sub)nets.
67 */
68 in_localaddr(in)
69 struct in_addr in;
70 {
71 register u_long i = ntohl(in.s_addr);
72 register struct in_ifaddr *ia;
73
74 if (subnetsarelocal) {
75 for (ia = in_ifaddr; ia; ia = ia->ia_next)
76 if ((i & ia->ia_netmask) == ia->ia_net)
77 return (1);
78 } else {
79 for (ia = in_ifaddr; ia; ia = ia->ia_next)
80 if ((i & ia->ia_subnetmask) == ia->ia_subnet)
81 return (1);
82 }
83 return (0);
84 }
85
86 /*
87 * Determine whether an IP address is in a reserved set of addresses
88 * that may not be forwarded, or whether datagrams to that destination
89 * may be forwarded.
90 */
91 in_canforward(in)
92 struct in_addr in;
93 {
94 register u_long i = ntohl(in.s_addr);
95 register u_long net;
96
97 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
98 return (0);
99 if (IN_CLASSA(i)) {
100 net = i & IN_CLASSA_NET;
101 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
102 return (0);
103 }
104 return (1);
105 }
106
107 /*
108 * Trim a mask in a sockaddr
109 */
110 void
in_socktrim(ap)111 in_socktrim(ap)
112 struct sockaddr_in *ap;
113 {
114 register char *cplim = (char *) &ap->sin_addr;
115 register char *cp = (char *) (&ap->sin_addr + 1);
116
117 ap->sin_len = 0;
118 while (--cp >= cplim)
119 if (*cp) {
120 (ap)->sin_len = cp - (char *) (ap) + 1;
121 break;
122 }
123 }
124
125 int in_interfaces; /* number of external internet interfaces */
126 extern struct ifnet loif;
127
128 /*
129 * Generic internet control operations (ioctl's).
130 * Ifp is 0 if not an interface-specific ioctl.
131 */
132 /* ARGSUSED */
133 in_control(so, cmd, data, ifp)
134 struct socket *so;
135 u_long cmd;
136 caddr_t data;
137 register struct ifnet *ifp;
138 {
139 register struct ifreq *ifr = (struct ifreq *)data;
140 register struct in_ifaddr *ia = 0;
141 register struct ifaddr *ifa;
142 struct in_ifaddr *oia;
143 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
144 struct sockaddr_in oldaddr;
145 int error, hostIsNew, maskIsNew;
146 u_long i;
147
148 /*
149 * Find address for this interface, if it exists.
150 */
151 if (ifp)
152 for (ia = in_ifaddr; ia; ia = ia->ia_next)
153 if (ia->ia_ifp == ifp)
154 break;
155
156 switch (cmd) {
157
158 case SIOCAIFADDR:
159 case SIOCDIFADDR:
160 if (ifra->ifra_addr.sin_family == AF_INET)
161 for (oia = ia; ia; ia = ia->ia_next) {
162 if (ia->ia_ifp == ifp &&
163 ia->ia_addr.sin_addr.s_addr ==
164 ifra->ifra_addr.sin_addr.s_addr)
165 break;
166 }
167 if (cmd == SIOCDIFADDR && ia == 0)
168 return (EADDRNOTAVAIL);
169 /* FALLTHROUGH */
170 case SIOCSIFADDR:
171 case SIOCSIFNETMASK:
172 case SIOCSIFDSTADDR:
173 if ((so->so_state & SS_PRIV) == 0)
174 return (EPERM);
175
176 if (ifp == 0)
177 panic("in_control");
178 if (ia == (struct in_ifaddr *)0) {
179 oia = (struct in_ifaddr *)
180 malloc(sizeof *oia, M_IFADDR, M_WAITOK);
181 if (oia == (struct in_ifaddr *)NULL)
182 return (ENOBUFS);
183 bzero((caddr_t)oia, sizeof *oia);
184 if (ia = in_ifaddr) {
185 for ( ; ia->ia_next; ia = ia->ia_next)
186 continue;
187 ia->ia_next = oia;
188 } else
189 in_ifaddr = oia;
190 ia = oia;
191 if (ifa = ifp->if_addrlist) {
192 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
193 continue;
194 ifa->ifa_next = (struct ifaddr *) ia;
195 } else
196 ifp->if_addrlist = (struct ifaddr *) ia;
197 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
198 ia->ia_ifa.ifa_dstaddr
199 = (struct sockaddr *)&ia->ia_dstaddr;
200 ia->ia_ifa.ifa_netmask
201 = (struct sockaddr *)&ia->ia_sockmask;
202 ia->ia_sockmask.sin_len = 8;
203 if (ifp->if_flags & IFF_BROADCAST) {
204 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
205 ia->ia_broadaddr.sin_family = AF_INET;
206 }
207 ia->ia_ifp = ifp;
208 if (ifp != &loif)
209 in_interfaces++;
210 }
211 break;
212
213 case SIOCSIFBRDADDR:
214 if ((so->so_state & SS_PRIV) == 0)
215 return (EPERM);
216 /* FALLTHROUGH */
217
218 case SIOCGIFADDR:
219 case SIOCGIFNETMASK:
220 case SIOCGIFDSTADDR:
221 case SIOCGIFBRDADDR:
222 if (ia == (struct in_ifaddr *)0)
223 return (EADDRNOTAVAIL);
224 break;
225 }
226 switch (cmd) {
227
228 case SIOCGIFADDR:
229 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
230 break;
231
232 case SIOCGIFBRDADDR:
233 if ((ifp->if_flags & IFF_BROADCAST) == 0)
234 return (EINVAL);
235 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
236 break;
237
238 case SIOCGIFDSTADDR:
239 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
240 return (EINVAL);
241 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
242 break;
243
244 case SIOCGIFNETMASK:
245 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
246 break;
247
248 case SIOCSIFDSTADDR:
249 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
250 return (EINVAL);
251 oldaddr = ia->ia_dstaddr;
252 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
253 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
254 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
255 ia->ia_dstaddr = oldaddr;
256 return (error);
257 }
258 if (ia->ia_flags & IFA_ROUTE) {
259 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
260 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
261 ia->ia_ifa.ifa_dstaddr =
262 (struct sockaddr *)&ia->ia_dstaddr;
263 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
264 }
265 break;
266
267 case SIOCSIFBRDADDR:
268 if ((ifp->if_flags & IFF_BROADCAST) == 0)
269 return (EINVAL);
270 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
271 break;
272
273 case SIOCSIFADDR:
274 return (in_ifinit(ifp, ia,
275 (struct sockaddr_in *) &ifr->ifr_addr, 1));
276
277 case SIOCSIFNETMASK:
278 i = ifra->ifra_addr.sin_addr.s_addr;
279 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
280 break;
281
282 case SIOCAIFADDR:
283 maskIsNew = 0;
284 hostIsNew = 1;
285 error = 0;
286 if (ia->ia_addr.sin_family == AF_INET) {
287 if (ifra->ifra_addr.sin_len == 0) {
288 ifra->ifra_addr = ia->ia_addr;
289 hostIsNew = 0;
290 } else if (ifra->ifra_addr.sin_addr.s_addr ==
291 ia->ia_addr.sin_addr.s_addr)
292 hostIsNew = 0;
293 }
294 if (ifra->ifra_mask.sin_len) {
295 in_ifscrub(ifp, ia);
296 ia->ia_sockmask = ifra->ifra_mask;
297 ia->ia_subnetmask =
298 ntohl(ia->ia_sockmask.sin_addr.s_addr);
299 maskIsNew = 1;
300 }
301 if ((ifp->if_flags & IFF_POINTOPOINT) &&
302 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
303 in_ifscrub(ifp, ia);
304 ia->ia_dstaddr = ifra->ifra_dstaddr;
305 maskIsNew = 1; /* We lie; but the effect's the same */
306 }
307 if (ifra->ifra_addr.sin_family == AF_INET &&
308 (hostIsNew || maskIsNew))
309 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
310 if ((ifp->if_flags & IFF_BROADCAST) &&
311 (ifra->ifra_broadaddr.sin_family == AF_INET))
312 ia->ia_broadaddr = ifra->ifra_broadaddr;
313 return (error);
314
315 case SIOCDIFADDR:
316 in_ifscrub(ifp, ia);
317 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
318 ifp->if_addrlist = ifa->ifa_next;
319 else {
320 while (ifa->ifa_next &&
321 (ifa->ifa_next != (struct ifaddr *)ia))
322 ifa = ifa->ifa_next;
323 if (ifa->ifa_next)
324 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
325 else
326 printf("Couldn't unlink inifaddr from ifp\n");
327 }
328 oia = ia;
329 if (oia == (ia = in_ifaddr))
330 in_ifaddr = ia->ia_next;
331 else {
332 while (ia->ia_next && (ia->ia_next != oia))
333 ia = ia->ia_next;
334 if (ia->ia_next)
335 ia->ia_next = oia->ia_next;
336 else
337 printf("Didn't unlink inifadr from list\n");
338 }
339 IFAFREE((&oia->ia_ifa));
340 break;
341
342 default:
343 if (ifp == 0 || ifp->if_ioctl == 0)
344 return (EOPNOTSUPP);
345 return ((*ifp->if_ioctl)(ifp, cmd, data));
346 }
347 return (0);
348 }
349
350 /*
351 * Delete any existing route for an interface.
352 */
353 void
in_ifscrub(ifp,ia)354 in_ifscrub(ifp, ia)
355 register struct ifnet *ifp;
356 register struct in_ifaddr *ia;
357 {
358
359 if ((ia->ia_flags & IFA_ROUTE) == 0)
360 return;
361 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
362 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
363 else
364 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
365 ia->ia_flags &= ~IFA_ROUTE;
366 }
367
368 /*
369 * Initialize an interface's internet address
370 * and routing table entry.
371 */
in_ifinit(ifp,ia,sin,scrub)372 in_ifinit(ifp, ia, sin, scrub)
373 register struct ifnet *ifp;
374 register struct in_ifaddr *ia;
375 struct sockaddr_in *sin;
376 int scrub;
377 {
378 register u_long i = ntohl(sin->sin_addr.s_addr);
379 struct sockaddr_in oldaddr;
380 int s = splimp(), flags = RTF_UP, error, ether_output();
381
382 oldaddr = ia->ia_addr;
383 ia->ia_addr = *sin;
384 /*
385 * Give the interface a chance to initialize
386 * if this is its first address,
387 * and to validate the address if necessary.
388 */
389 if (ifp->if_ioctl &&
390 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
391 splx(s);
392 ia->ia_addr = oldaddr;
393 return (error);
394 }
395 if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
396 ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
397 ia->ia_ifa.ifa_flags |= RTF_CLONING;
398 }
399 splx(s);
400 if (scrub) {
401 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
402 in_ifscrub(ifp, ia);
403 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
404 }
405 if (IN_CLASSA(i))
406 ia->ia_netmask = IN_CLASSA_NET;
407 else if (IN_CLASSB(i))
408 ia->ia_netmask = IN_CLASSB_NET;
409 else
410 ia->ia_netmask = IN_CLASSC_NET;
411 /*
412 * The subnet mask usually includes at least the standard network part,
413 * but may may be smaller in the case of supernetting.
414 * If it is set, we believe it.
415 */
416 if (ia->ia_subnetmask == 0) {
417 ia->ia_subnetmask = ia->ia_netmask;
418 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
419 } else
420 ia->ia_netmask &= ia->ia_subnetmask;
421 ia->ia_net = i & ia->ia_netmask;
422 ia->ia_subnet = i & ia->ia_subnetmask;
423 in_socktrim(&ia->ia_sockmask);
424 /*
425 * Add route for the network.
426 */
427 ia->ia_ifa.ifa_metric = ifp->if_metric;
428 if (ifp->if_flags & IFF_BROADCAST) {
429 ia->ia_broadaddr.sin_addr.s_addr =
430 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
431 ia->ia_netbroadcast.s_addr =
432 htonl(ia->ia_net | ~ ia->ia_netmask);
433 } else if (ifp->if_flags & IFF_LOOPBACK) {
434 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
435 flags |= RTF_HOST;
436 } else if (ifp->if_flags & IFF_POINTOPOINT) {
437 if (ia->ia_dstaddr.sin_family != AF_INET)
438 return (0);
439 flags |= RTF_HOST;
440 }
441 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
442 ia->ia_flags |= IFA_ROUTE;
443 /*
444 * If the interface supports multicast, join the "all hosts"
445 * multicast group on that interface.
446 */
447 if (ifp->if_flags & IFF_MULTICAST) {
448 struct in_addr addr;
449
450 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
451 in_addmulti(&addr, ifp);
452 }
453 return (error);
454 }
455
456
457 /*
458 * Return 1 if the address might be a local broadcast address.
459 */
460 in_broadcast(in, ifp)
461 struct in_addr in;
462 struct ifnet *ifp;
463 {
464 register struct ifaddr *ifa;
465 u_long t;
466
467 if (in.s_addr == INADDR_BROADCAST ||
468 in.s_addr == INADDR_ANY)
469 return 1;
470 if ((ifp->if_flags & IFF_BROADCAST) == 0)
471 return 0;
472 t = ntohl(in.s_addr);
473 /*
474 * Look through the list of addresses for a match
475 * with a broadcast address.
476 */
477 #define ia ((struct in_ifaddr *)ifa)
478 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
479 if (ifa->ifa_addr->sa_family == AF_INET &&
480 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
481 in.s_addr == ia->ia_netbroadcast.s_addr ||
482 /*
483 * Check for old-style (host 0) broadcast.
484 */
485 t == ia->ia_subnet || t == ia->ia_net))
486 return 1;
487 return (0);
488 #undef ia
489 }
490 /*
491 * Add an address to the list of IP multicast addresses for a given interface.
492 */
493 struct in_multi *
in_addmulti(ap,ifp)494 in_addmulti(ap, ifp)
495 register struct in_addr *ap;
496 register struct ifnet *ifp;
497 {
498 register struct in_multi *inm;
499 struct ifreq ifr;
500 struct in_ifaddr *ia;
501 int s = splnet();
502
503 /*
504 * See if address already in list.
505 */
506 IN_LOOKUP_MULTI(*ap, ifp, inm);
507 if (inm != NULL) {
508 /*
509 * Found it; just increment the reference count.
510 */
511 ++inm->inm_refcount;
512 }
513 else {
514 /*
515 * New address; allocate a new multicast record
516 * and link it into the interface's multicast list.
517 */
518 inm = (struct in_multi *)malloc(sizeof(*inm),
519 M_IPMADDR, M_NOWAIT);
520 if (inm == NULL) {
521 splx(s);
522 return (NULL);
523 }
524 inm->inm_addr = *ap;
525 inm->inm_ifp = ifp;
526 inm->inm_refcount = 1;
527 IFP_TO_IA(ifp, ia);
528 if (ia == NULL) {
529 free(inm, M_IPMADDR);
530 splx(s);
531 return (NULL);
532 }
533 inm->inm_ia = ia;
534 inm->inm_next = ia->ia_multiaddrs;
535 ia->ia_multiaddrs = inm;
536 /*
537 * Ask the network driver to update its multicast reception
538 * filter appropriately for the new address.
539 */
540 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
541 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
542 if ((ifp->if_ioctl == NULL) ||
543 (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
544 ia->ia_multiaddrs = inm->inm_next;
545 free(inm, M_IPMADDR);
546 splx(s);
547 return (NULL);
548 }
549 /*
550 * Let IGMP know that we have joined a new IP multicast group.
551 */
552 igmp_joingroup(inm);
553 }
554 splx(s);
555 return (inm);
556 }
557
558 /*
559 * Delete a multicast address record.
560 */
561 int
in_delmulti(inm)562 in_delmulti(inm)
563 register struct in_multi *inm;
564 {
565 register struct in_multi **p;
566 struct ifreq ifr;
567 int s = splnet();
568
569 if (--inm->inm_refcount == 0) {
570 /*
571 * No remaining claims to this record; let IGMP know that
572 * we are leaving the multicast group.
573 */
574 igmp_leavegroup(inm);
575 /*
576 * Unlink from list.
577 */
578 for (p = &inm->inm_ia->ia_multiaddrs;
579 *p != inm;
580 p = &(*p)->inm_next)
581 continue;
582 *p = (*p)->inm_next;
583 /*
584 * Notify the network driver to update its multicast reception
585 * filter.
586 */
587 ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
588 ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
589 inm->inm_addr;
590 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
591 (caddr_t)&ifr);
592 free(inm, M_IPMADDR);
593 }
594 splx(s);
595 }
596 #endif
597