| 1141 | #endif |
| 1142 | |
| 1143 | static int |
| 1144 | udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, |
| 1145 | struct mbuf *control, struct thread *td, int flags) |
| 1146 | { |
| 1147 | struct udpiphdr *ui; |
| 1148 | int len = m->m_pkthdr.len; |
| 1149 | struct in_addr faddr, laddr; |
| 1150 | struct cmsghdr *cm; |
| 1151 | struct inpcbinfo *pcbinfo; |
| 1152 | struct sockaddr_in *sin, src; |
| 1153 | struct epoch_tracker et; |
| 1154 | int cscov_partial = 0; |
| 1155 | int error = 0; |
| 1156 | int ipflags = 0; |
| 1157 | u_short fport, lport; |
| 1158 | u_char tos; |
| 1159 | uint8_t pr; |
| 1160 | uint16_t cscov = 0; |
| 1161 | uint32_t flowid = 0; |
| 1162 | uint8_t flowtype = M_HASHTYPE_NONE; |
| 1163 | |
| 1164 | if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) { |
| 1165 | if (control) |
| 1166 | m_freem(control); |
| 1167 | m_freem(m); |
| 1168 | return (EMSGSIZE); |
| 1169 | } |
| 1170 | |
| 1171 | src.sin_family = 0; |
| 1172 | sin = (struct sockaddr_in *)addr; |
| 1173 | |
| 1174 | /* |
| 1175 | * udp_output() may need to temporarily bind or connect the current |
| 1176 | * inpcb. As such, we don't know up front whether we will need the |
| 1177 | * pcbinfo lock or not. Do any work to decide what is needed up |
| 1178 | * front before acquiring any locks. |
| 1179 | * |
| 1180 | * We will need network epoch in either case, to safely lookup into |
| 1181 | * pcb hash. |
| 1182 | */ |
| 1183 | if (sin == NULL || |
| 1184 | (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) |
| 1185 | INP_WLOCK(inp); |
| 1186 | else |
| 1187 | INP_RLOCK(inp); |
| 1188 | NET_EPOCH_ENTER(et); |
| 1189 | tos = inp->inp_ip_tos; |
| 1190 | if (control != NULL) { |
| 1191 | /* |
| 1192 | * XXX: Currently, we assume all the optional information is |
| 1193 | * stored in a single mbuf. |
| 1194 | */ |
| 1195 | if (control->m_next) { |
| 1196 | m_freem(control); |
| 1197 | error = EINVAL; |
| 1198 | goto release; |
| 1199 | } |
| 1200 | for (; control->m_len > 0; |
no test coverage detected