| 1160 | } |
| 1161 | |
| 1162 | static int |
| 1163 | bpfwrite(struct cdev *dev, struct uio *uio, int ioflag) |
| 1164 | { |
| 1165 | struct route ro; |
| 1166 | struct sockaddr dst; |
| 1167 | struct epoch_tracker et; |
| 1168 | struct bpf_if *bp; |
| 1169 | struct bpf_d *d; |
| 1170 | struct ifnet *ifp; |
| 1171 | struct mbuf *m, *mc; |
| 1172 | int error, hlen; |
| 1173 | |
| 1174 | error = devfs_get_cdevpriv((void **)&d); |
| 1175 | if (error != 0) |
| 1176 | return (error); |
| 1177 | |
| 1178 | NET_EPOCH_ENTER(et); |
| 1179 | BPFD_LOCK(d); |
| 1180 | BPF_PID_REFRESH_CUR(d); |
| 1181 | counter_u64_add(d->bd_wcount, 1); |
| 1182 | if ((bp = d->bd_bif) == NULL) { |
| 1183 | error = ENXIO; |
| 1184 | goto out_locked; |
| 1185 | } |
| 1186 | |
| 1187 | ifp = bp->bif_ifp; |
| 1188 | if ((ifp->if_flags & IFF_UP) == 0) { |
| 1189 | error = ENETDOWN; |
| 1190 | goto out_locked; |
| 1191 | } |
| 1192 | |
| 1193 | if (uio->uio_resid == 0) |
| 1194 | goto out_locked; |
| 1195 | |
| 1196 | bzero(&dst, sizeof(dst)); |
| 1197 | m = NULL; |
| 1198 | hlen = 0; |
| 1199 | |
| 1200 | /* |
| 1201 | * Take extra reference, unlock d and exit from epoch section, |
| 1202 | * since bpf_movein() can sleep. |
| 1203 | */ |
| 1204 | bpfd_ref(d); |
| 1205 | NET_EPOCH_EXIT(et); |
| 1206 | BPFD_UNLOCK(d); |
| 1207 | |
| 1208 | error = bpf_movein(uio, (int)bp->bif_dlt, ifp, |
| 1209 | &m, &dst, &hlen, d); |
| 1210 | |
| 1211 | if (error != 0) { |
| 1212 | counter_u64_add(d->bd_wdcount, 1); |
| 1213 | bpfd_rele(d); |
| 1214 | return (error); |
| 1215 | } |
| 1216 | |
| 1217 | BPFD_LOCK(d); |
| 1218 | /* |
| 1219 | * Check that descriptor is still attached to the interface. |
nothing calls this directly
no test coverage detected