|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)in.c 7.2 (Berkeley) 11/23/86
7: */
8:
9: #include "param.h"
10: #include "ioctl.h"
11: #include "mbuf.h"
12: #include "protosw.h"
13: #include "socket.h"
14: #include "socketvar.h"
15: #include "uio.h"
16: #include "dir.h"
17: #include "user.h"
18: #include "in_systm.h"
19: #include "../net/if.h"
20: #include "../net/route.h"
21: #include "../net/af.h"
22: #include "in.h"
23: #include "in_var.h"
24:
25: #ifdef INET
26: inet_hash(sin, hp)
27: register struct sockaddr_in *sin;
28: struct afhash *hp;
29: {
30: register u_long n;
31:
32: n = in_netof(sin->sin_addr);
33: if (n)
34: while ((n & 0xff) == 0)
35: n >>= 8;
36: hp->afh_nethash = n;
37: hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
38: }
39:
40: inet_netmatch(sin1, sin2)
41: struct sockaddr_in *sin1, *sin2;
42: {
43:
44: return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
45: }
46:
47: /*
48: * Formulate an Internet address from network + host.
49: */
50: struct in_addr
51: in_makeaddr(net, host)
52: u_long net, host;
53: {
54: register struct in_ifaddr *ia;
55: register u_long mask;
56: u_long addr;
57:
58: if (IN_CLASSA(net))
59: mask = IN_CLASSA_HOST;
60: else if (IN_CLASSB(net))
61: mask = IN_CLASSB_HOST;
62: else
63: mask = IN_CLASSC_HOST;
64: for (ia = in_ifaddr; ia; ia = ia->ia_next)
65: if ((ia->ia_netmask & net) == ia->ia_net) {
66: mask = ~ia->ia_subnetmask;
67: break;
68: }
69: addr = htonl(net | (host & mask));
70: return (*(struct in_addr *)&addr);
71: }
72:
73: /*
74: * Return the network number from an internet address.
75: */
76: u_long
77: in_netof(in)
78: struct in_addr in;
79: {
80: register u_long i = ntohl(in.s_addr);
81: register u_long net;
82: register struct in_ifaddr *ia;
83:
84: if (IN_CLASSA(i))
85: net = i & IN_CLASSA_NET;
86: else if (IN_CLASSB(i))
87: net = i & IN_CLASSB_NET;
88: else
89: net = i & IN_CLASSC_NET;
90:
91: /*
92: * Check whether network is a subnet;
93: * if so, return subnet number.
94: */
95: for (ia = in_ifaddr; ia; ia = ia->ia_next)
96: if (net == ia->ia_net)
97: return (i & ia->ia_subnetmask);
98: return (net);
99: }
100:
101: /*
102: * Return the host portion of an internet address.
103: */
104: u_long
105: in_lnaof(in)
106: struct in_addr in;
107: {
108: register u_long i = ntohl(in.s_addr);
109: register u_long net, host;
110: register struct in_ifaddr *ia;
111:
112: if (IN_CLASSA(i)) {
113: net = i & IN_CLASSA_NET;
114: host = i & IN_CLASSA_HOST;
115: } else if (IN_CLASSB(i)) {
116: net = i & IN_CLASSB_NET;
117: host = i & IN_CLASSB_HOST;
118: } else {
119: net = i & IN_CLASSC_NET;
120: host = i & IN_CLASSC_HOST;
121: }
122:
123: /*
124: * Check whether network is a subnet;
125: * if so, use the modified interpretation of `host'.
126: */
127: for (ia = in_ifaddr; ia; ia = ia->ia_next)
128: if (net == ia->ia_net)
129: return (host &~ ia->ia_subnetmask);
130: return (host);
131: }
132:
133: #ifndef SUBNETSARELOCAL
134: #define SUBNETSARELOCAL 1
135: #endif
136: int subnetsarelocal = SUBNETSARELOCAL;
137: /*
138: * Return 1 if an internet address is for a ``local'' host
139: * (one to which we have a connection). If subnetsarelocal
140: * is true, this includes other subnets of the local net.
141: * Otherwise, it includes only the directly-connected (sub)nets.
142: */
143: in_localaddr(in)
144: struct in_addr in;
145: {
146: register u_long i = ntohl(in.s_addr);
147: register u_long net;
148: register struct in_ifaddr *ia;
149:
150: if (IN_CLASSA(i))
151: net = i & IN_CLASSA_NET;
152: else if (IN_CLASSB(i))
153: net = i & IN_CLASSB_NET;
154: else
155: net = i & IN_CLASSC_NET;
156:
157: for (ia = in_ifaddr; ia; ia = ia->ia_next)
158: if (net == (subnetsarelocal ? ia->ia_net : ia->ia_subnet))
159: return (1);
160: return (0);
161: }
162:
163: int in_interfaces; /* number of external internet interfaces */
164: extern struct ifnet loif;
165:
166: /*
167: * Generic internet control operations (ioctl's).
168: * Ifp is 0 if not an interface-specific ioctl.
169: */
170: /* ARGSUSED */
171: in_control(so, cmd, data, ifp)
172: struct socket *so;
173: int cmd;
174: caddr_t data;
175: register struct ifnet *ifp;
176: {
177: register struct ifreq *ifr = (struct ifreq *)data;
178: register struct in_ifaddr *ia = 0;
179: u_long tmp;
180: struct ifaddr *ifa;
181: struct mbuf *m;
182: int error;
183:
184: /*
185: * Find address for this interface, if it exists.
186: */
187: if (ifp)
188: for (ia = in_ifaddr; ia; ia = ia->ia_next)
189: if (ia->ia_ifp == ifp)
190: break;
191:
192: switch (cmd) {
193:
194: case SIOCSIFADDR:
195: case SIOCSIFNETMASK:
196: case SIOCSIFDSTADDR:
197: if (!suser())
198: return (u.u_error);
199:
200: if (ifp == 0)
201: panic("in_control");
202: if (ia == (struct in_ifaddr *)0) {
203: m = m_getclr(M_WAIT, MT_IFADDR);
204: if (m == (struct mbuf *)NULL)
205: return (ENOBUFS);
206: if (ia = in_ifaddr) {
207: for ( ; ia->ia_next; ia = ia->ia_next)
208: ;
209: ia->ia_next = mtod(m, struct in_ifaddr *);
210: } else
211: in_ifaddr = mtod(m, struct in_ifaddr *);
212: ia = mtod(m, struct in_ifaddr *);
213: if (ifa = ifp->if_addrlist) {
214: for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
215: ;
216: ifa->ifa_next = (struct ifaddr *) ia;
217: } else
218: ifp->if_addrlist = (struct ifaddr *) ia;
219: ia->ia_ifp = ifp;
220: IA_SIN(ia)->sin_family = AF_INET;
221: if (ifp != &loif)
222: in_interfaces++;
223: }
224: break;
225:
226: case SIOCSIFBRDADDR:
227: if (!suser())
228: return (u.u_error);
229: /* FALLTHROUGH */
230:
231: default:
232: if (ia == (struct in_ifaddr *)0)
233: return (EADDRNOTAVAIL);
234: break;
235: }
236:
237: switch (cmd) {
238:
239: case SIOCGIFADDR:
240: ifr->ifr_addr = ia->ia_addr;
241: break;
242:
243: case SIOCGIFBRDADDR:
244: if ((ifp->if_flags & IFF_BROADCAST) == 0)
245: return (EINVAL);
246: ifr->ifr_dstaddr = ia->ia_broadaddr;
247: break;
248:
249: case SIOCGIFDSTADDR:
250: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
251: return (EINVAL);
252: ifr->ifr_dstaddr = ia->ia_dstaddr;
253: break;
254:
255: case SIOCGIFNETMASK:
256: #define satosin(sa) ((struct sockaddr_in *)(sa))
257: satosin(&ifr->ifr_addr)->sin_family = AF_INET;
258: satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
259: break;
260:
261: case SIOCSIFDSTADDR:
262: {
263: struct sockaddr oldaddr;
264:
265: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
266: return (EINVAL);
267: oldaddr = ia->ia_dstaddr;
268: ia->ia_dstaddr = ifr->ifr_dstaddr;
269: if (ifp->if_ioctl &&
270: (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
271: ia->ia_dstaddr = oldaddr;
272: return (error);
273: }
274: if (ia->ia_flags & IFA_ROUTE) {
275: rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT,
276: RTF_HOST);
277: rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
278: RTF_HOST|RTF_UP);
279: }
280: }
281: break;
282:
283: case SIOCSIFBRDADDR:
284: if ((ifp->if_flags & IFF_BROADCAST) == 0)
285: return (EINVAL);
286: ia->ia_broadaddr = ifr->ifr_broadaddr;
287: tmp = ntohl(satosin(&ia->ia_broadaddr)->sin_addr.s_addr);
288: if ((tmp &~ ia->ia_subnetmask) == ~ia->ia_subnetmask)
289: tmp |= ~ia->ia_netmask;
290: else if ((tmp &~ ia->ia_subnetmask) == 0)
291: tmp &= ia->ia_netmask;
292: ia->ia_netbroadcast.s_addr = htonl(tmp);
293: break;
294:
295: case SIOCSIFADDR:
296: return (in_ifinit(ifp, ia, &ifr->ifr_addr));
297:
298: case SIOCSIFNETMASK:
299: ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
300: break;
301:
302: default:
303: if (ifp == 0 || ifp->if_ioctl == 0)
304: return (EOPNOTSUPP);
305: return ((*ifp->if_ioctl)(ifp, cmd, data));
306: }
307: return (0);
308: }
309:
310: /*
311: * Initialize an interface's internet address
312: * and routing table entry.
313: */
314: in_ifinit(ifp, ia, sin)
315: register struct ifnet *ifp;
316: register struct in_ifaddr *ia;
317: struct sockaddr_in *sin;
318: {
319: register u_long i = ntohl(sin->sin_addr.s_addr);
320: struct sockaddr oldaddr;
321: struct sockaddr_in netaddr;
322: int s = splimp(), error;
323:
324: oldaddr = ia->ia_addr;
325: ia->ia_addr = *(struct sockaddr *)sin;
326:
327: /*
328: * Give the interface a chance to initialize
329: * if this is its first address,
330: * and to validate the address if necessary.
331: */
332: if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
333: splx(s);
334: ia->ia_addr = oldaddr;
335: return (error);
336: }
337:
338: /*
339: * Delete any previous route for an old address.
340: */
341: bzero((caddr_t)&netaddr, sizeof (netaddr));
342: netaddr.sin_family = AF_INET;
343: if (ia->ia_flags & IFA_ROUTE) {
344: if (ifp->if_flags & IFF_LOOPBACK)
345: rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST);
346: else if (ifp->if_flags & IFF_POINTOPOINT)
347: rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT,
348: RTF_HOST);
349: else {
350: netaddr.sin_addr = in_makeaddr(ia->ia_subnet,
351: INADDR_ANY);
352: rtinit((struct sockaddr *)&netaddr, &oldaddr,
353: (int)SIOCDELRT, 0);
354: }
355: ia->ia_flags &= ~IFA_ROUTE;
356: }
357: if (IN_CLASSA(i))
358: ia->ia_netmask = IN_CLASSA_NET;
359: else if (IN_CLASSB(i))
360: ia->ia_netmask = IN_CLASSB_NET;
361: else
362: ia->ia_netmask = IN_CLASSC_NET;
363: ia->ia_net = i & ia->ia_netmask;
364: /*
365: * The subnet mask includes at least the standard network part,
366: * but may already have been set to a larger value.
367: */
368: ia->ia_subnetmask |= ia->ia_netmask;
369: ia->ia_subnet = i & ia->ia_subnetmask;
370: if (ifp->if_flags & IFF_BROADCAST) {
371: ia->ia_broadaddr.sa_family = AF_INET;
372: ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr =
373: in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
374: ia->ia_netbroadcast.s_addr =
375: htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
376: }
377: splx(s);
378: /*
379: * Add route for the network.
380: */
381: if (ifp->if_flags & IFF_LOOPBACK)
382: rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT,
383: RTF_HOST|RTF_UP);
384: else if (ifp->if_flags & IFF_POINTOPOINT)
385: rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
386: RTF_HOST|RTF_UP);
387: else {
388: netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
389: rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
390: (int)SIOCADDRT, RTF_UP);
391: }
392: ia->ia_flags |= IFA_ROUTE;
393: return (0);
394: }
395:
396: /*
397: * Return address info for specified internet network.
398: */
399: struct in_ifaddr *
400: in_iaonnetof(net)
401: u_long net;
402: {
403: register struct in_ifaddr *ia;
404:
405: for (ia = in_ifaddr; ia; ia = ia->ia_next)
406: if (ia->ia_subnet == net)
407: return (ia);
408: return ((struct in_ifaddr *)0);
409: }
410:
411: /*
412: * Return 1 if the address is a local broadcast address.
413: */
414: in_broadcast(in)
415: struct in_addr in;
416: {
417: register struct in_ifaddr *ia;
418:
419: /*
420: * Look through the list of addresses for a match
421: * with a broadcast address.
422: */
423: for (ia = in_ifaddr; ia; ia = ia->ia_next)
424: if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr ==
425: in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST))
426: return (1);
427: return (0);
428: }
429: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.