BSD 4_3 release
[unix-history] / usr / src / sys / netns / ns.c
CommitLineData
8ae0e4b4 1/*
0880b18e 2 * Copyright (c) 1984, 1985, 1986 Regents of the University of California.
8ae0e4b4
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
95f51977 6 * @(#)ns.c 7.1 (Berkeley) 6/5/86
8ae0e4b4 7 */
de9bc7de
KS
8
9#include "param.h"
10#include "mbuf.h"
11#include "ioctl.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
19
20#include "../net/if.h"
21#include "../net/route.h"
22#include "../net/af.h"
23
24#include "ns.h"
25#include "ns_if.h"
26
27#ifdef NS
28
29struct ns_ifaddr *ns_ifaddr;
30
31ns_hash(sns, hp)
32 register struct sockaddr_ns *sns;
33 struct afhash *hp;
34{
35 register long hash = 0;
36 register u_short *s = sns->sns_addr.x_host.s_host;
f1e269d4
KS
37 union {
38 union ns_net net_e;
39 long long_e;
40 } net;
de9bc7de 41
f1e269d4
KS
42 net.net_e = sns->sns_addr.x_net;
43 hp->afh_nethash = net.long_e;
de9bc7de
KS
44 hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
45 hp->afh_hosthash = hash;
46}
47
48
49ns_netmatch(sns1, sns2)
50 struct sockaddr_ns *sns1, *sns2;
51{
52
f1e269d4 53 return (ns_neteq(sns1->sns_addr, sns2->sns_addr));
de9bc7de
KS
54}
55
56/*
57 * Generic internet control operations (ioctl's).
58 */
f97be0c9 59/* ARGSUSED */
de9bc7de
KS
60ns_control(so, cmd, data, ifp)
61 struct socket *so;
62 int cmd;
63 caddr_t data;
64 register struct ifnet *ifp;
65{
66 register struct ifreq *ifr = (struct ifreq *)data;
67 register struct ns_ifaddr *ia;
68 struct ifaddr *ifa;
69 struct mbuf *m;
de9bc7de 70
de9bc7de
KS
71 /*
72 * Find address for this interface, if it exists.
73 */
8b659320 74 if (ifp == 0)
4353fa68 75 return (EADDRNOTAVAIL);
de9bc7de
KS
76 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
77 if (ia->ia_ifp == ifp)
78 break;
79
80 switch (cmd) {
81
82 case SIOCGIFADDR:
4353fa68
KS
83 if (ia == (struct ns_ifaddr *)0)
84 return (EADDRNOTAVAIL);
85 ifr->ifr_addr = ia->ia_addr;
86 return (0);
87
88
de9bc7de 89 case SIOCGIFBRDADDR:
4353fa68
KS
90 if (ia == (struct ns_ifaddr *)0)
91 return (EADDRNOTAVAIL);
92 if ((ifp->if_flags & IFF_BROADCAST) == 0)
93 return (EINVAL);
94 ifr->ifr_dstaddr = ia->ia_broadaddr;
95 return (0);
96
de9bc7de
KS
97 case SIOCGIFDSTADDR:
98 if (ia == (struct ns_ifaddr *)0)
99 return (EADDRNOTAVAIL);
4353fa68
KS
100 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
101 return (EINVAL);
102 ifr->ifr_dstaddr = ia->ia_dstaddr;
103 return (0);
104 }
105
106 if (!suser())
107 return (u.u_error);
108
109 switch (cmd) {
de9bc7de 110
de9bc7de 111 case SIOCSIFADDR:
8b659320 112 case SIOCSIFDSTADDR:
de9bc7de
KS
113 if (ia == (struct ns_ifaddr *)0) {
114 m = m_getclr(M_WAIT, MT_IFADDR);
115 if (m == (struct mbuf *)NULL)
116 return (ENOBUFS);
117 if (ia = ns_ifaddr) {
118 for ( ; ia->ia_next; ia = ia->ia_next)
119 ;
120 ia->ia_next = mtod(m, struct ns_ifaddr *);
121 } else
122 ns_ifaddr = mtod(m, struct ns_ifaddr *);
123 ia = mtod(m, struct ns_ifaddr *);
124 if (ifa = ifp->if_addrlist) {
125 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
126 ;
127 ifa->ifa_next = (struct ifaddr *) ia;
128 } else
129 ifp->if_addrlist = (struct ifaddr *) ia;
130 ia->ia_ifp = ifp;
131 IA_SNS(ia)->sns_family = AF_NS;
132 }
8b659320
KS
133 }
134
135 switch (cmd) {
136
137 case SIOCSIFDSTADDR:
138 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
139 return (EINVAL);
140 if (ia->ia_flags & IFA_ROUTE) {
141 rtinit(&ia->ia_dstaddr, &ia->ia_addr,
142 (int)SIOCDELRT, RTF_HOST);
143 ia->ia_flags &= ~IFA_ROUTE;
144 }
145 if (ifp->if_ioctl) {
146 int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
147 if (error)
148 return (error);
149 }
150 ia->ia_dstaddr = ifr->ifr_dstaddr;
151 return (0);
152
153 case SIOCSIFADDR:
de9bc7de
KS
154 return
155 (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr));
156
157 default:
158 if (ifp->if_ioctl == 0)
159 return (EOPNOTSUPP);
160 return ((*ifp->if_ioctl)(ifp, cmd, data));
161 }
de9bc7de
KS
162}
163
164/*
165 * Initialize an interface's internet address
166 * and routing table entry.
167 */
168ns_ifinit(ifp, ia, sns)
169 register struct ifnet *ifp;
170 register struct ns_ifaddr *ia;
171 struct sockaddr_ns *sns;
172{
173 struct sockaddr_ns netaddr;
174 register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host);
175 int s = splimp(), error;
176
177 /*
178 * The convention we shall adopt for naming is that
179 * a supplied address of zero means that "we don't care".
180 * if there is a single interface, use the address of that
181 * interface as our 6 byte host address.
182 * if there are multiple interfaces, use any address already
183 * used.
184 *
185 * If we have gotten into trouble and want to reset back to
186 * virginity, we recognize a request of the broadcast address.
187 */
188 if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) {
189 ns_thishost = ns_zerohost;
190 splx(s);
8b659320 191 return (0);
de9bc7de
KS
192 }
193
194 /*
195 * Delete any previous route for an old address.
196 */
de9bc7de
KS
197 bzero((caddr_t)&netaddr, sizeof (netaddr));
198 netaddr.sns_family = AF_NS;
199 netaddr.sns_addr.x_host = ns_broadhost;
200 netaddr.sns_addr.x_net = ia->ia_net;
201 if (ia->ia_flags & IFA_ROUTE) {
202 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
8b659320
KS
203 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
204 (int)SIOCDELRT, 0);
de9bc7de 205 } else
8b659320
KS
206 rtinit(&ia->ia_dstaddr, &ia->ia_addr,
207 (int)SIOCDELRT, RTF_HOST);
de9bc7de
KS
208 }
209
210 /*
211 * Set up new addresses.
212 */
213 ia->ia_addr = *(struct sockaddr *)sns;
214 ia->ia_net = sns->sns_addr.x_net;
215 netaddr.sns_addr.x_net = ia->ia_net;
216 if (ifp->if_flags & IFF_BROADCAST) {
217 ia->ia_broadaddr = * (struct sockaddr *) &netaddr;
218 }
8b659320 219
de9bc7de
KS
220 /*
221 * Give the interface a chance to initialize
222 * if this is its first address,
223 * and to validate the address if necessary.
224 */
de9bc7de
KS
225 if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
226 if (ifp->if_ioctl &&
227 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
228 splx(s);
229 return (error);
230 }
231 ns_thishost = *h;
232 } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
233 || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
234 *h = ns_thishost;
235 if (ifp->if_ioctl &&
236 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
237 splx(s);
238 return (error);
239 }
8b659320 240 if (!ns_hosteqnh(ns_thishost,*h)) {
de9bc7de
KS
241 splx(s);
242 return (EINVAL);
243 }
244 } else {
245 splx(s);
8b659320 246 return (EINVAL);
de9bc7de 247 }
8b659320 248
de9bc7de
KS
249 /*
250 * Add route for the network.
251 */
8b659320
KS
252 if (ifp->if_flags & IFF_POINTOPOINT)
253 rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
de9bc7de 254 RTF_HOST|RTF_UP);
8b659320
KS
255 else
256 rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT,
257 RTF_UP);
de9bc7de 258 ia->ia_flags |= IFA_ROUTE;
8b659320 259 return (0);
de9bc7de
KS
260}
261
262/*
263 * Return address info for specified internet network.
264 */
265struct ns_ifaddr *
46aa06a9
KS
266ns_iaonnetof(dst)
267 register struct ns_addr *dst;
de9bc7de
KS
268{
269 register struct ns_ifaddr *ia;
46aa06a9 270 register struct ns_addr *compare;
8b659320
KS
271 register struct ifnet *ifp;
272 struct ns_ifaddr *ia_maybe = 0;
f1e269d4 273 union ns_net net = dst->x_net;
de9bc7de 274
46aa06a9 275 for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
8b659320
KS
276 if (ifp = ia->ia_ifp) {
277 if (ifp->if_flags & IFF_POINTOPOINT) {
278 compare = &satons_addr(ia->ia_dstaddr);
279 if (ns_hosteq(*dst, *compare))
280 return (ia);
f1e269d4 281 if (ns_neteqnn(net, ia->ia_net))
8b659320
KS
282 ia_maybe = ia;
283 } else {
f1e269d4 284 if (ns_neteqnn(net, ia->ia_net))
46aa06a9
KS
285 return (ia);
286 }
287 }
288 }
289 return (ia_maybe);
de9bc7de
KS
290}
291#endif