ip_output.c (147f74d17602153ead22790c53715830ab6892b7) | ip_output.c (ef39adf007d3a9125dc4a03ece5a586c1519e8b8) |
---|---|
1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 43 unchanged lines hidden (view full) --- 52#include <net/route.h> 53 54#include <netinet/in.h> 55#include <netinet/in_systm.h> 56#include <netinet/ip.h> 57#include <netinet/in_pcb.h> 58#include <netinet/in_var.h> 59#include <netinet/ip_var.h> | 1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 43 unchanged lines hidden (view full) --- 52#include <net/route.h> 53 54#include <netinet/in.h> 55#include <netinet/in_systm.h> 56#include <netinet/ip.h> 57#include <netinet/in_pcb.h> 58#include <netinet/in_var.h> 59#include <netinet/ip_var.h> |
60#include <netinet/ip_options.h> |
|
60 61#include <machine/in_cksum.h> 62 63static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options"); 64 65#ifdef IPSEC 66#include <netinet6/ipsec.h> 67#include <netkey/key.h> --- 19 unchanged lines hidden (view full) --- 87u_short ip_id; 88 89#ifdef MBUF_STRESS_TEST 90int mbuf_frag_size = 0; 91SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW, 92 &mbuf_frag_size, 0, "Fragment outgoing mbufs to this size"); 93#endif 94 | 61 62#include <machine/in_cksum.h> 63 64static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options"); 65 66#ifdef IPSEC 67#include <netinet6/ipsec.h> 68#include <netkey/key.h> --- 19 unchanged lines hidden (view full) --- 88u_short ip_id; 89 90#ifdef MBUF_STRESS_TEST 91int mbuf_frag_size = 0; 92SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW, 93 &mbuf_frag_size, 0, "Fragment outgoing mbufs to this size"); 94#endif 95 |
95static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); | |
96static struct ifnet *ip_multicast_if(struct in_addr *, int *); 97static void ip_mloopback 98 (struct ifnet *, struct mbuf *, struct sockaddr_in *, int); 99static int ip_getmoptions(struct inpcb *, struct sockopt *); | 96static struct ifnet *ip_multicast_if(struct in_addr *, int *); 97static void ip_mloopback 98 (struct ifnet *, struct mbuf *, struct sockaddr_in *, int); 99static int ip_getmoptions(struct inpcb *, struct sockopt *); |
100static int ip_pcbopts(struct inpcb *, int, struct mbuf *); | |
101static int ip_setmoptions(struct inpcb *, struct sockopt *); | 100static int ip_setmoptions(struct inpcb *, struct sockopt *); |
102static struct ip_moptions *ip_findmoptions(struct inpcb *inp); | |
103 | 101 |
104int ip_optcopy(struct ip *, struct ip *); | |
105 | 102 |
106 | |
107extern struct protosw inetsw[]; 108 109/* 110 * IP output. The packet in mbuf chain m contains a skeletal IP 111 * header (with len, off, ttl, proto, tos, src, dst). 112 * The mbuf chain containing the packet will be freed. 113 * The mbuf opt, if present, will not be freed. 114 * In the IP forwarding case, the packet will arrive with options already --- 933 unchanged lines hidden (view full) --- 1048 * in the existing chain instead of rearranging it. 1049 */ 1050 m = m_pullup(m, offset + sizeof(u_short)); 1051 } 1052 *(u_short *)(m->m_data + offset) = csum; 1053} 1054 1055/* | 103extern struct protosw inetsw[]; 104 105/* 106 * IP output. The packet in mbuf chain m contains a skeletal IP 107 * header (with len, off, ttl, proto, tos, src, dst). 108 * The mbuf chain containing the packet will be freed. 109 * The mbuf opt, if present, will not be freed. 110 * In the IP forwarding case, the packet will arrive with options already --- 933 unchanged lines hidden (view full) --- 1044 * in the existing chain instead of rearranging it. 1045 */ 1046 m = m_pullup(m, offset + sizeof(u_short)); 1047 } 1048 *(u_short *)(m->m_data + offset) = csum; 1049} 1050 1051/* |
1056 * Insert IP options into preformed packet. 1057 * Adjust IP destination as required for IP source routing, 1058 * as indicated by a non-zero in_addr at the start of the options. 1059 * 1060 * XXX This routine assumes that the packet has no options in place. 1061 */ 1062static struct mbuf * 1063ip_insertoptions(m, opt, phlen) 1064 register struct mbuf *m; 1065 struct mbuf *opt; 1066 int *phlen; 1067{ 1068 register struct ipoption *p = mtod(opt, struct ipoption *); 1069 struct mbuf *n; 1070 register struct ip *ip = mtod(m, struct ip *); 1071 unsigned optlen; 1072 1073 optlen = opt->m_len - sizeof(p->ipopt_dst); 1074 if (optlen + ip->ip_len > IP_MAXPACKET) { 1075 *phlen = 0; 1076 return (m); /* XXX should fail */ 1077 } 1078 if (p->ipopt_dst.s_addr) 1079 ip->ip_dst = p->ipopt_dst; 1080 if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) { 1081 MGETHDR(n, M_DONTWAIT, MT_DATA); 1082 if (n == NULL) { 1083 *phlen = 0; 1084 return (m); 1085 } 1086 M_MOVE_PKTHDR(n, m); 1087 n->m_pkthdr.rcvif = NULL; 1088#ifdef MAC 1089 mac_copy_mbuf(m, n); 1090#endif 1091 n->m_pkthdr.len += optlen; 1092 m->m_len -= sizeof(struct ip); 1093 m->m_data += sizeof(struct ip); 1094 n->m_next = m; 1095 m = n; 1096 m->m_len = optlen + sizeof(struct ip); 1097 m->m_data += max_linkhdr; 1098 bcopy(ip, mtod(m, void *), sizeof(struct ip)); 1099 } else { 1100 m->m_data -= optlen; 1101 m->m_len += optlen; 1102 m->m_pkthdr.len += optlen; 1103 bcopy(ip, mtod(m, void *), sizeof(struct ip)); 1104 } 1105 ip = mtod(m, struct ip *); 1106 bcopy(p->ipopt_list, ip + 1, optlen); 1107 *phlen = sizeof(struct ip) + optlen; 1108 ip->ip_v = IPVERSION; 1109 ip->ip_hl = *phlen >> 2; 1110 ip->ip_len += optlen; 1111 return (m); 1112} 1113 1114/* 1115 * Copy options from ip to jp, 1116 * omitting those not copied during fragmentation. 1117 */ 1118int 1119ip_optcopy(ip, jp) 1120 struct ip *ip, *jp; 1121{ 1122 register u_char *cp, *dp; 1123 int opt, optlen, cnt; 1124 1125 cp = (u_char *)(ip + 1); 1126 dp = (u_char *)(jp + 1); 1127 cnt = (ip->ip_hl << 2) - sizeof (struct ip); 1128 for (; cnt > 0; cnt -= optlen, cp += optlen) { 1129 opt = cp[0]; 1130 if (opt == IPOPT_EOL) 1131 break; 1132 if (opt == IPOPT_NOP) { 1133 /* Preserve for IP mcast tunnel's LSRR alignment. */ 1134 *dp++ = IPOPT_NOP; 1135 optlen = 1; 1136 continue; 1137 } 1138 1139 KASSERT(cnt >= IPOPT_OLEN + sizeof(*cp), 1140 ("ip_optcopy: malformed ipv4 option")); 1141 optlen = cp[IPOPT_OLEN]; 1142 KASSERT(optlen >= IPOPT_OLEN + sizeof(*cp) && optlen <= cnt, 1143 ("ip_optcopy: malformed ipv4 option")); 1144 1145 /* bogus lengths should have been caught by ip_dooptions */ 1146 if (optlen > cnt) 1147 optlen = cnt; 1148 if (IPOPT_COPIED(opt)) { 1149 bcopy(cp, dp, optlen); 1150 dp += optlen; 1151 } 1152 } 1153 for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++) 1154 *dp++ = IPOPT_EOL; 1155 return (optlen); 1156} 1157 1158/* | |
1159 * IP socket option processing. 1160 */ 1161int 1162ip_ctloutput(so, sopt) 1163 struct socket *so; 1164 struct sockopt *sopt; 1165{ 1166 struct inpcb *inp = sotoinpcb(so); --- 293 unchanged lines hidden (view full) --- 1460 break; 1461 } 1462 break; 1463 } 1464 return (error); 1465} 1466 1467/* | 1052 * IP socket option processing. 1053 */ 1054int 1055ip_ctloutput(so, sopt) 1056 struct socket *so; 1057 struct sockopt *sopt; 1058{ 1059 struct inpcb *inp = sotoinpcb(so); --- 293 unchanged lines hidden (view full) --- 1353 break; 1354 } 1355 break; 1356 } 1357 return (error); 1358} 1359 1360/* |
1468 * Set up IP options in pcb for insertion in output packets. 1469 * Store in mbuf with pointer in pcbopt, adding pseudo-option 1470 * with destination address if source routed. 1471 */ 1472static int 1473ip_pcbopts(struct inpcb *inp, int optname, struct mbuf *m) 1474{ 1475 register int cnt, optlen; 1476 register u_char *cp; 1477 struct mbuf **pcbopt; 1478 u_char opt; 1479 1480 INP_LOCK_ASSERT(inp); 1481 1482 pcbopt = &inp->inp_options; 1483 1484 /* turn off any old options */ 1485 if (*pcbopt) 1486 (void)m_free(*pcbopt); 1487 *pcbopt = 0; 1488 if (m == NULL || m->m_len == 0) { 1489 /* 1490 * Only turning off any previous options. 1491 */ 1492 if (m != NULL) 1493 (void)m_free(m); 1494 return (0); 1495 } 1496 1497 if (m->m_len % sizeof(int32_t)) 1498 goto bad; 1499 /* 1500 * IP first-hop destination address will be stored before 1501 * actual options; move other options back 1502 * and clear it when none present. 1503 */ 1504 if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN]) 1505 goto bad; 1506 cnt = m->m_len; 1507 m->m_len += sizeof(struct in_addr); 1508 cp = mtod(m, u_char *) + sizeof(struct in_addr); 1509 bcopy(mtod(m, void *), cp, (unsigned)cnt); 1510 bzero(mtod(m, void *), sizeof(struct in_addr)); 1511 1512 for (; cnt > 0; cnt -= optlen, cp += optlen) { 1513 opt = cp[IPOPT_OPTVAL]; 1514 if (opt == IPOPT_EOL) 1515 break; 1516 if (opt == IPOPT_NOP) 1517 optlen = 1; 1518 else { 1519 if (cnt < IPOPT_OLEN + sizeof(*cp)) 1520 goto bad; 1521 optlen = cp[IPOPT_OLEN]; 1522 if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) 1523 goto bad; 1524 } 1525 switch (opt) { 1526 1527 default: 1528 break; 1529 1530 case IPOPT_LSRR: 1531 case IPOPT_SSRR: 1532 /* 1533 * user process specifies route as: 1534 * ->A->B->C->D 1535 * D must be our final destination (but we can't 1536 * check that since we may not have connected yet). 1537 * A is first hop destination, which doesn't appear in 1538 * actual IP option, but is stored before the options. 1539 */ 1540 if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr)) 1541 goto bad; 1542 m->m_len -= sizeof(struct in_addr); 1543 cnt -= sizeof(struct in_addr); 1544 optlen -= sizeof(struct in_addr); 1545 cp[IPOPT_OLEN] = optlen; 1546 /* 1547 * Move first hop before start of options. 1548 */ 1549 bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t), 1550 sizeof(struct in_addr)); 1551 /* 1552 * Then copy rest of options back 1553 * to close up the deleted entry. 1554 */ 1555 bcopy((&cp[IPOPT_OFFSET+1] + sizeof(struct in_addr)), 1556 &cp[IPOPT_OFFSET+1], 1557 (unsigned)cnt - (IPOPT_MINOFF - 1)); 1558 break; 1559 } 1560 } 1561 if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr)) 1562 goto bad; 1563 *pcbopt = m; 1564 return (0); 1565 1566bad: 1567 (void)m_free(m); 1568 return (EINVAL); 1569} 1570 1571/* | |
1572 * XXX 1573 * The whole multicast option thing needs to be re-thought. 1574 * Several of these options are equally applicable to non-multicast 1575 * transmission, and one (IP_MULTICAST_TTL) totally duplicates a 1576 * standard option (IP_TTL). 1577 */ 1578 1579/* --- 502 unchanged lines hidden --- | 1361 * XXX 1362 * The whole multicast option thing needs to be re-thought. 1363 * Several of these options are equally applicable to non-multicast 1364 * transmission, and one (IP_MULTICAST_TTL) totally duplicates a 1365 * standard option (IP_TTL). 1366 */ 1367 1368/* --- 502 unchanged lines hidden --- |