1 /* ns_ip.c 6.1 85/05/30 */ 2 3 /* 4 * Software interface driver for encapsulating ns in ip. 5 */ 6 7 #ifdef NSIP 8 #include "param.h" 9 #include "systm.h" 10 #include "mbuf.h" 11 #include "socket.h" 12 #include "errno.h" 13 #include "ioctl.h" 14 15 #include "../net/if.h" 16 #include "../net/netisr.h" 17 #include "../net/route.h" 18 19 #include "../netinet/in.h" 20 #include "../netinet/in_systm.h" 21 #include "../netinet/in_var.h" 22 #include "../netinet/ip.h" 23 #include "../netinet/ip_var.h" 24 25 #ifdef vax 26 #include "../vax/mtpr.h" 27 #endif 28 29 #include "../netns/ns.h" 30 #include "../netns/ns_if.h" 31 #include "../netns/idp.h" 32 33 struct ifnet_en { 34 struct ifnet ifen_ifnet; 35 struct route ifen_route; 36 struct in_addr ifen_src; 37 struct in_addr ifen_dst; 38 }; 39 40 int nsipoutput(), nsipioctl(); 41 #define LOMTU (1024+512); 42 43 struct ifnet nsipif; 44 union ns_net nsip_net; 45 struct mbuf *nsip_list; /* list of all hosts and gateways or 46 broadcast addrs */ 47 48 struct mbuf * 49 nsipattach() 50 { 51 register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); 52 register struct ifnet *ifp; 53 register struct sockaddr_in *sin; 54 55 if (m==0) return (0); 56 m->m_off = MMINOFF; 57 m->m_len = sizeof(struct ifnet_en); 58 m->m_next = nsip_list; 59 nsip_list = m; 60 ifp = mtod(m, struct ifnet *); 61 62 ifp->if_name = "nsip"; 63 ifp->if_mtu = LOMTU; 64 ifp->if_ioctl = nsipioctl; 65 ifp->if_output = nsipoutput; 66 ifp->if_flags = IFF_POINTOPOINT; 67 ifp->if_unit = nsipif.if_unit++; 68 if_attach(ifp); 69 return(dtom(ifp)); 70 } 71 72 73 /* 74 * Process an ioctl request. 75 */ 76 /* ARGSUSED */ 77 nsipioctl(ifp, cmd, data) 78 register struct ifnet *ifp; 79 int cmd; 80 caddr_t data; 81 { 82 int error = 0; 83 84 switch (cmd) { 85 86 case SIOCSIFADDR: 87 ifp->if_flags |= IFF_UP; 88 /* 89 * Everything else is done at a higher level. 90 */ 91 break; 92 93 default: 94 error = EINVAL; 95 } 96 return (error); 97 } 98 99 struct mbuf *nsip_badlen; 100 struct mbuf *nsip_lastin; 101 int nsip_hold_input; 102 103 idpip_input(m0) 104 struct mbuf *m0; 105 { 106 register struct ip *ip; 107 register struct idp *idp; 108 register struct mbuf *m; 109 register struct ifqueue *ifq = &nsintrq; 110 int len, s; 111 112 if(nsip_hold_input) { 113 if(nsip_lastin) { 114 m_free(nsip_lastin); 115 } 116 nsip_lastin = m_copy(m0, 0, M_COPYALL); 117 } 118 /* 119 * Get IP and IDP header together in first mbuf. 120 */ 121 nsipif.if_ipackets++; 122 m = m0; 123 s = sizeof (struct ip) + sizeof (struct idp); 124 if ((m->m_off > MMAXOFF || m->m_len < s) && 125 (m = m_pullup(m, s))==0) { 126 nsipif.if_ierrors++; 127 return; 128 } 129 ip = mtod(m, struct ip *); 130 if (ip->ip_hl > (sizeof (struct ip) >> 2)) 131 ip_stripoptions(ip, (struct mbuf *)0); 132 133 /* 134 * Make mbuf data length reflect IDP length. 135 * If not enough data to reflect IDP length, drop. 136 */ 137 m->m_off += sizeof (struct ip); 138 m->m_len -= sizeof (struct ip); 139 idp = mtod(m, struct idp *); 140 len = ntohs(idp->idp_len); 141 if (ip->ip_len != len) { 142 if (len > ip->ip_len) { 143 nsipif.if_ierrors++; 144 if(nsip_badlen) m_freem(nsip_badlen); 145 nsip_badlen = m; 146 return; 147 } 148 m_adj(m, len - ip->ip_len); 149 /* ip->ip_len = len; */ 150 } 151 /* 152 * Deliver to NS 153 */ 154 s = splimp(); 155 if (IF_QFULL(ifq)) { 156 IF_DROP(ifq); 157 m_freem(m0); 158 splx(s); 159 return (ENOBUFS); 160 } 161 IF_ENQUEUE(ifq, m0); 162 schednetisr(NETISR_NS); 163 splx(s); 164 return (0); 165 bad: 166 m_freem(m); 167 return (0); 168 } 169 170 nsipoutput(ifn, m0, dst) 171 struct ifnet_en *ifn; 172 struct mbuf *m0; 173 struct sockaddr *dst; 174 { 175 176 register struct mbuf *m = dtom(ifn); 177 register struct ip *ip; 178 register struct route *ro = &(ifn->ifen_route); 179 register int len = 0; 180 struct in_addr in_src, in_dst; 181 register struct idp *idp = mtod(m0, struct idp *); 182 int error; 183 184 if (m->m_len != sizeof(struct ifnet_en)) { 185 printf("nsipoutput: bad dst ifp %x\n", ifn); 186 goto bad; 187 } 188 ifn->ifen_ifnet.if_opackets++; 189 nsipif.if_opackets++; 190 191 192 /* 193 * Calculate data length and make space 194 * for IP header. 195 */ 196 len = ntohs(idp->idp_len); 197 m = m0; 198 if(m->m_off < MMINOFF + sizeof (struct ip)) { 199 m = m_get(M_DONTWAIT, MT_HEADER); 200 if (m == 0) { 201 m_freem(m0); 202 return (ENOBUFS); 203 } 204 m->m_off = MMAXOFF - sizeof (struct ip); 205 m->m_len = sizeof (struct ip); 206 m->m_next = m0; 207 } else { 208 m->m_off -= sizeof (struct ip); 209 m->m_len += sizeof (struct ip); 210 } 211 /* 212 * Fill in IP header. 213 */ 214 ip = mtod(m, struct ip *); 215 *(long *)ip = 0; 216 ip->ip_p = IPPROTO_PUP; 217 ip->ip_src = ifn->ifen_src; 218 ip->ip_dst = ifn->ifen_dst; 219 ip->ip_len = (u_short)len + sizeof (struct ip); 220 ip->ip_ttl = MAXTTL; 221 222 /* 223 * Output final datagram. 224 */ 225 error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST)); 226 if (error) { 227 ifn->ifen_ifnet.if_oerrors++; 228 ifn->ifen_ifnet.if_ierrors = error; 229 } 230 return (error); 231 bad: 232 m_freem(m0); 233 return(ENETUNREACH); 234 } 235 236 struct ifreq ifr = {"nsip0"}; 237 238 nsip_route(m) 239 register struct mbuf *m; 240 { 241 register struct nsip_req *rq = mtod(m, struct nsip_req *); 242 struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns; 243 struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip; 244 int flags = rq->rq_flags; 245 struct ifnet *ifp; 246 struct route ro; 247 struct ifnet_en *ifn; 248 int error; 249 struct sockaddr_in *dst; 250 struct sockaddr_in *src; 251 /* 252 * First, determine if we can get to the destination 253 */ 254 bzero((caddr_t)&ro, sizeof (ro)); 255 ro.ro_dst = *(struct sockaddr *)ip_dst; 256 dst = (struct sockaddr_in *)& ro.ro_dst; 257 rtalloc(&ro); 258 if (ro.ro_rt == 0 || (ifp = ro.ro_rt->rt_ifp) == 0) { 259 return (ENETUNREACH); 260 } 261 /* 262 * And see how he's going to get back to us: 263 */ 264 { 265 register struct in_ifaddr *ia; 266 struct ifnet *ifp = ro.ro_rt->rt_ifp; 267 268 for (ia = in_ifaddr; ia; ia = ia->ia_next) 269 if (ia->ia_ifp == ifp) 270 break; 271 if (ia == 0) 272 ia = in_ifaddr; 273 if (ia == 0) { 274 return (EADDRNOTAVAIL); 275 } 276 src = (struct sockaddr_in *)&ia->ia_addr; 277 } 278 /* 279 * Is there space? 280 */ 281 m = nsipattach(); 282 if (m==NULL) {return (ENOBUFS);} 283 ifn = mtod(m, struct ifnet_en *); 284 285 ro.ro_rt->rt_use++; 286 ifn->ifen_route = ro; 287 ifn->ifen_dst = ip_dst->sin_addr; 288 ifn->ifen_src = src->sin_addr; 289 290 /* 291 * now configure this as a point to point link 292 */ 293 ifr.ifr_name[4] = '0' + nsipif.if_unit - 1; 294 ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst; 295 return(ns_control((struct socket *)0, SIOCSIFADDR, (caddr_t)&ifr, 296 (struct ifnet *)ifn)); 297 } 298 #endif 299