1 /* 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)ip_output.c 7.17 (Berkeley) 03/01/90 18 */ 19 20 #include "param.h" 21 #include "malloc.h" 22 #include "mbuf.h" 23 #include "errno.h" 24 #include "protosw.h" 25 #include "socket.h" 26 #include "socketvar.h" 27 28 #include "../net/if.h" 29 #include "../net/route.h" 30 31 #include "in.h" 32 #include "in_pcb.h" 33 #include "in_systm.h" 34 #include "in_var.h" 35 #include "ip.h" 36 #include "ip_var.h" 37 38 #ifdef vax 39 #include "machine/mtpr.h" 40 #endif 41 42 struct mbuf *ip_insertoptions(); 43 44 /* 45 * IP output. The packet in mbuf chain m contains a skeletal IP 46 * header (with len, off, ttl, proto, tos, src, dst). 47 * The mbuf chain containing the packet will be freed. 48 * The mbuf opt, if present, will not be freed. 49 */ 50 ip_output(m0, opt, ro, flags) 51 struct mbuf *m0; 52 struct mbuf *opt; 53 struct route *ro; 54 int flags; 55 { 56 register struct ip *ip, *mhip; 57 register struct ifnet *ifp; 58 register struct mbuf *m = m0; 59 register int hlen = sizeof (struct ip); 60 int len, off, error = 0; 61 struct route iproute; 62 struct sockaddr_in *dst; 63 64 if ((m->m_flags & M_PKTHDR) == 0) 65 panic("ip_output no HDR"); 66 if (opt) { 67 m = ip_insertoptions(m, opt, &len); 68 hlen = len; 69 } 70 ip = mtod(m, struct ip *); 71 /* 72 * Fill in IP header. 73 */ 74 if ((flags & IP_FORWARDING) == 0) { 75 ip->ip_v = IPVERSION; 76 ip->ip_off &= IP_DF; 77 ip->ip_id = htons(ip_id++); 78 ip->ip_hl = hlen >> 2; 79 } else { 80 hlen = ip->ip_hl << 2; 81 ipstat.ips_localout++; 82 } 83 /* 84 * Route packet. 85 */ 86 if (ro == 0) { 87 ro = &iproute; 88 bzero((caddr_t)ro, sizeof (*ro)); 89 } 90 dst = (struct sockaddr_in *)&ro->ro_dst; 91 /* 92 * If there is a cached route, 93 * check that it is to the same destination 94 * and is still up. If not, free it and try again. 95 */ 96 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 97 dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { 98 RTFREE(ro->ro_rt); 99 ro->ro_rt = (struct rtentry *)0; 100 } 101 if (ro->ro_rt == 0) { 102 dst->sin_family = AF_INET; 103 dst->sin_len = sizeof(*dst); 104 dst->sin_addr = ip->ip_dst; 105 } 106 /* 107 * If routing to interface only, 108 * short circuit routing lookup. 109 */ 110 if (flags & IP_ROUTETOIF) { 111 struct in_ifaddr *ia; 112 113 ia = (struct in_ifaddr *)ifa_ifwithdstaddr((struct sockaddr *)dst); 114 if (ia == 0) 115 ia = in_iaonnetof(in_netof(ip->ip_dst)); 116 if (ia == 0) { 117 error = ENETUNREACH; 118 goto bad; 119 } 120 ifp = ia->ia_ifp; 121 } else { 122 if (ro->ro_rt == 0) 123 rtalloc(ro); 124 if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { 125 if (in_localaddr(ip->ip_dst)) 126 error = EHOSTUNREACH; 127 else 128 error = ENETUNREACH; 129 goto bad; 130 } 131 ro->ro_rt->rt_use++; 132 if (ro->ro_rt->rt_flags & RTF_GATEWAY) 133 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; 134 } 135 #ifndef notdef 136 /* 137 * If source address not specified yet, use address 138 * of outgoing interface. 139 */ 140 if (ip->ip_src.s_addr == INADDR_ANY) { 141 register struct in_ifaddr *ia; 142 143 for (ia = in_ifaddr; ia; ia = ia->ia_next) 144 if (ia->ia_ifp == ifp) { 145 ip->ip_src = IA_SIN(ia)->sin_addr; 146 break; 147 } 148 } 149 #endif 150 /* 151 * Look for broadcast address and 152 * and verify user is allowed to send 153 * such a packet. 154 */ 155 if (in_broadcast(dst->sin_addr)) { 156 if ((ifp->if_flags & IFF_BROADCAST) == 0) { 157 error = EADDRNOTAVAIL; 158 goto bad; 159 } 160 if ((flags & IP_ALLOWBROADCAST) == 0) { 161 error = EACCES; 162 goto bad; 163 } 164 /* don't allow broadcast messages to be fragmented */ 165 if (ip->ip_len > ifp->if_mtu) { 166 error = EMSGSIZE; 167 goto bad; 168 } 169 m->m_flags |= M_BCAST; 170 } 171 172 /* 173 * If small enough for interface, can just send directly. 174 */ 175 if (ip->ip_len <= ifp->if_mtu) { 176 ip->ip_len = htons((u_short)ip->ip_len); 177 ip->ip_off = htons((u_short)ip->ip_off); 178 ip->ip_sum = 0; 179 ip->ip_sum = in_cksum(m, hlen); 180 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); 181 goto done; 182 } 183 ipstat.ips_fragmented++; 184 /* 185 * Too large for interface; fragment if possible. 186 * Must be able to put at least 8 bytes per fragment. 187 */ 188 if (ip->ip_off & IP_DF) { 189 error = EMSGSIZE; 190 goto bad; 191 } 192 len = (ifp->if_mtu - hlen) &~ 7; 193 if (len < 8) { 194 error = EMSGSIZE; 195 goto bad; 196 } 197 198 { 199 int mhlen, firstlen = len; 200 struct mbuf **mnext = &m->m_nextpkt; 201 202 /* 203 * Loop through length of segment after first fragment, 204 * make new header and copy data of each part and link onto chain. 205 */ 206 m0 = m; 207 mhlen = sizeof (struct ip); 208 for (off = hlen + len; off < ip->ip_len; off += len) { 209 MGETHDR(m, M_DONTWAIT, MT_HEADER); 210 if (m == 0) { 211 error = ENOBUFS; 212 goto sendorfree; 213 } 214 m->m_data += max_linkhdr; 215 mhip = mtod(m, struct ip *); 216 *mhip = *ip; 217 if (hlen > sizeof (struct ip)) { 218 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 219 mhip->ip_hl = mhlen >> 2; 220 } 221 m->m_len = mhlen; 222 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); 223 if (ip->ip_off & IP_MF) 224 mhip->ip_off |= IP_MF; 225 if (off + len >= ip->ip_len) 226 len = ip->ip_len - off; 227 else 228 mhip->ip_off |= IP_MF; 229 mhip->ip_len = htons((u_short)(len + mhlen)); 230 m->m_next = m_copy(m0, off, len); 231 if (m->m_next == 0) { 232 error = ENOBUFS; /* ??? */ 233 goto sendorfree; 234 } 235 m->m_pkthdr.len = mhlen + len; 236 m->m_pkthdr.rcvif = (struct ifnet *)0; 237 mhip->ip_off = htons((u_short)mhip->ip_off); 238 mhip->ip_sum = 0; 239 mhip->ip_sum = in_cksum(m, mhlen); 240 *mnext = m; 241 mnext = &m->m_nextpkt; 242 ipstat.ips_ofragments++; 243 } 244 /* 245 * Update first fragment by trimming what's been copied out 246 * and updating header, then send each fragment (in order). 247 */ 248 m = m0; 249 m_adj(m, hlen + firstlen - ip->ip_len); 250 m->m_pkthdr.len = hlen + firstlen; 251 ip->ip_len = htons((u_short)m->m_pkthdr.len); 252 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); 253 ip->ip_sum = 0; 254 ip->ip_sum = in_cksum(m, hlen); 255 sendorfree: 256 for (m = m0; m; m = m0) { 257 m0 = m->m_nextpkt; 258 m->m_nextpkt = 0; 259 if (error == 0) 260 error = (*ifp->if_output)(ifp, m, 261 (struct sockaddr *)dst); 262 else 263 m_freem(m); 264 } 265 } 266 done: 267 if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) 268 RTFREE(ro->ro_rt); 269 return (error); 270 bad: 271 m_freem(m0); 272 goto done; 273 } 274 275 /* 276 * Insert IP options into preformed packet. 277 * Adjust IP destination as required for IP source routing, 278 * as indicated by a non-zero in_addr at the start of the options. 279 */ 280 struct mbuf * 281 ip_insertoptions(m, opt, phlen) 282 register struct mbuf *m; 283 struct mbuf *opt; 284 int *phlen; 285 { 286 register struct ipoption *p = mtod(opt, struct ipoption *); 287 struct mbuf *n; 288 register struct ip *ip = mtod(m, struct ip *); 289 unsigned optlen; 290 291 optlen = opt->m_len - sizeof(p->ipopt_dst); 292 if (p->ipopt_dst.s_addr) 293 ip->ip_dst = p->ipopt_dst; 294 if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) { 295 MGETHDR(n, M_DONTWAIT, MT_HEADER); 296 if (n == 0) 297 return (m); 298 n->m_pkthdr.len = m->m_pkthdr.len + optlen; 299 m->m_len -= sizeof(struct ip); 300 m->m_data += sizeof(struct ip); 301 n->m_next = m; 302 m = n; 303 m->m_len = optlen + sizeof(struct ip); 304 m->m_data += max_linkhdr; 305 bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); 306 } else { 307 m->m_data -= optlen; 308 m->m_len += optlen; 309 m->m_pkthdr.len += optlen; 310 ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); 311 } 312 ip = mtod(m, struct ip *); 313 bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen); 314 *phlen = sizeof(struct ip) + optlen; 315 ip->ip_len += optlen; 316 return (m); 317 } 318 319 /* 320 * Copy options from ip to jp, 321 * omitting those not copied during fragmentation. 322 */ 323 ip_optcopy(ip, jp) 324 struct ip *ip, *jp; 325 { 326 register u_char *cp, *dp; 327 int opt, optlen, cnt; 328 329 cp = (u_char *)(ip + 1); 330 dp = (u_char *)(jp + 1); 331 cnt = (ip->ip_hl << 2) - sizeof (struct ip); 332 for (; cnt > 0; cnt -= optlen, cp += optlen) { 333 opt = cp[0]; 334 if (opt == IPOPT_EOL) 335 break; 336 if (opt == IPOPT_NOP) 337 optlen = 1; 338 else 339 optlen = cp[IPOPT_OLEN]; 340 /* bogus lengths should have been caught by ip_dooptions */ 341 if (optlen > cnt) 342 optlen = cnt; 343 if (IPOPT_COPIED(opt)) { 344 bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen); 345 dp += optlen; 346 } 347 } 348 for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++) 349 *dp++ = IPOPT_EOL; 350 return (optlen); 351 } 352 353 /* 354 * IP socket option processing. 355 */ 356 ip_ctloutput(op, so, level, optname, m) 357 int op; 358 struct socket *so; 359 int level, optname; 360 struct mbuf **m; 361 { 362 int error = 0; 363 struct inpcb *inp = sotoinpcb(so); 364 365 if (level != IPPROTO_IP) 366 error = EINVAL; 367 else switch (op) { 368 369 case PRCO_SETOPT: 370 switch (optname) { 371 case IP_OPTIONS: 372 return (ip_pcbopts(&inp->inp_options, *m)); 373 374 default: 375 error = EINVAL; 376 break; 377 } 378 break; 379 380 case PRCO_GETOPT: 381 switch (optname) { 382 case IP_OPTIONS: 383 *m = m_get(M_WAIT, MT_SOOPTS); 384 if (inp->inp_options) { 385 (*m)->m_len = inp->inp_options->m_len; 386 bcopy(mtod(inp->inp_options, caddr_t), 387 mtod(*m, caddr_t), (unsigned)(*m)->m_len); 388 } else 389 (*m)->m_len = 0; 390 break; 391 default: 392 error = EINVAL; 393 break; 394 } 395 break; 396 } 397 if (op == PRCO_SETOPT && *m) 398 (void)m_free(*m); 399 return (error); 400 } 401 402 /* 403 * Set up IP options in pcb for insertion in output packets. 404 * Store in mbuf with pointer in pcbopt, adding pseudo-option 405 * with destination address if source routed. 406 */ 407 ip_pcbopts(pcbopt, m) 408 struct mbuf **pcbopt; 409 register struct mbuf *m; 410 { 411 register cnt, optlen; 412 register u_char *cp; 413 u_char opt; 414 415 /* turn off any old options */ 416 if (*pcbopt) 417 (void)m_free(*pcbopt); 418 *pcbopt = 0; 419 if (m == (struct mbuf *)0 || m->m_len == 0) { 420 /* 421 * Only turning off any previous options. 422 */ 423 if (m) 424 (void)m_free(m); 425 return (0); 426 } 427 428 #ifndef vax 429 if (m->m_len % sizeof(long)) 430 goto bad; 431 #endif 432 /* 433 * IP first-hop destination address will be stored before 434 * actual options; move other options back 435 * and clear it when none present. 436 */ 437 if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN]) 438 goto bad; 439 cnt = m->m_len; 440 m->m_len += sizeof(struct in_addr); 441 cp = mtod(m, u_char *) + sizeof(struct in_addr); 442 ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt); 443 bzero(mtod(m, caddr_t), sizeof(struct in_addr)); 444 445 for (; cnt > 0; cnt -= optlen, cp += optlen) { 446 opt = cp[IPOPT_OPTVAL]; 447 if (opt == IPOPT_EOL) 448 break; 449 if (opt == IPOPT_NOP) 450 optlen = 1; 451 else { 452 optlen = cp[IPOPT_OLEN]; 453 if (optlen <= IPOPT_OLEN || optlen > cnt) 454 goto bad; 455 } 456 switch (opt) { 457 458 default: 459 break; 460 461 case IPOPT_LSRR: 462 case IPOPT_SSRR: 463 /* 464 * user process specifies route as: 465 * ->A->B->C->D 466 * D must be our final destination (but we can't 467 * check that since we may not have connected yet). 468 * A is first hop destination, which doesn't appear in 469 * actual IP option, but is stored before the options. 470 */ 471 if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr)) 472 goto bad; 473 m->m_len -= sizeof(struct in_addr); 474 cnt -= sizeof(struct in_addr); 475 optlen -= sizeof(struct in_addr); 476 cp[IPOPT_OLEN] = optlen; 477 /* 478 * Move first hop before start of options. 479 */ 480 bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t), 481 sizeof(struct in_addr)); 482 /* 483 * Then copy rest of options back 484 * to close up the deleted entry. 485 */ 486 ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] + 487 sizeof(struct in_addr)), 488 (caddr_t)&cp[IPOPT_OFFSET+1], 489 (unsigned)cnt + sizeof(struct in_addr)); 490 break; 491 } 492 } 493 if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr)) 494 goto bad; 495 *pcbopt = m; 496 return (0); 497 498 bad: 499 (void)m_free(m); 500 return (EINVAL); 501 } 502