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 ---