99 |
}, |
}, |
100 |
}; |
}; |
101 |
|
|
102 |
#ifdef IPC_DEBUG /* Only used by DEBUG(()) */ |
#ifdef DEBUG /* Only used with dprintf() */ |
103 |
static char *ntoa(uint32_t addr) |
static char *ntoa(uint32_t addr) |
104 |
{ |
{ |
105 |
struct in_addr in = { addr }; |
struct in_addr in = { addr }; |
106 |
return inet_ntoa(in); |
return inet_ntoa(in); |
107 |
} |
} |
108 |
#endif |
#endif /* DEBUG */ |
109 |
|
|
110 |
/* |
/* |
111 |
* Send a packet. The options are listed in iov[1...iov_len]. |
* Send a packet. The options are listed in iov[1...iov_len-1]. |
112 |
* iov[0] is reserved for the bootp packet header. |
* iov[0] is reserved for the bootp packet header. |
113 |
*/ |
*/ |
114 |
int packet_send(struct netdev *dev, struct iovec *iov, int iov_len) |
int packet_send(struct netdev *dev, struct iovec *iov, int iov_len) |
115 |
{ |
{ |
116 |
struct sockaddr_ll sll; |
struct sockaddr_ll sll; |
117 |
struct msghdr msg = { |
struct msghdr msg; |
|
.msg_name = &sll, |
|
|
.msg_namelen = sizeof(sll), |
|
|
.msg_iov = iov, |
|
|
.msg_iovlen = iov_len, |
|
|
.msg_control = NULL, |
|
|
.msg_controllen = 0, |
|
|
.msg_flags = 0 |
|
|
}; |
|
118 |
int i, len = 0; |
int i, len = 0; |
119 |
|
|
120 |
|
memset(&sll, 0, sizeof(sll)); |
121 |
|
msg.msg_name = &sll; |
122 |
|
msg.msg_namelen = sizeof(sll); |
123 |
|
msg.msg_iov = iov; |
124 |
|
msg.msg_iovlen = iov_len; |
125 |
|
msg.msg_control = NULL; |
126 |
|
msg.msg_controllen = 0; |
127 |
|
msg.msg_flags = 0; |
128 |
|
|
129 |
if (cfg_local_port != LOCAL_PORT) { |
if (cfg_local_port != LOCAL_PORT) { |
130 |
ipudp_hdrs.udp.source = htons(cfg_local_port); |
ipudp_hdrs.udp.source = htons(cfg_local_port); |
131 |
ipudp_hdrs.udp.dest = htons(cfg_remote_port); |
ipudp_hdrs.udp.dest = htons(cfg_remote_port); |
132 |
} |
} |
133 |
|
|
134 |
DEBUG(("\n udp src %d dst %d", ntohs(ipudp_hdrs.udp.source), |
dprintf("\n udp src %d dst %d", ntohs(ipudp_hdrs.udp.source), |
135 |
ntohs(ipudp_hdrs.udp.dest))); |
ntohs(ipudp_hdrs.udp.dest)); |
136 |
|
|
137 |
DEBUG(("\n ip src %s ", ntoa(ipudp_hdrs.ip.saddr))); |
dprintf("\n ip src %s ", ntoa(ipudp_hdrs.ip.saddr)); |
138 |
DEBUG(("dst %s ", ntoa(ipudp_hdrs.ip.daddr))); |
dprintf("dst %s ", ntoa(ipudp_hdrs.ip.daddr)); |
139 |
|
|
140 |
/* |
/* |
141 |
* Glue in the ip+udp header iovec |
* Glue in the ip+udp header iovec |
161 |
|
|
162 |
ipudp_hdrs.udp.len = htons(len - sizeof(struct iphdr)); |
ipudp_hdrs.udp.len = htons(len - sizeof(struct iphdr)); |
163 |
|
|
164 |
DEBUG(("\n bytes %d\n", len)); |
dprintf("\n bytes %d\n", len); |
165 |
|
|
166 |
return sendmsg(pkt_fd, &msg, 0); |
return sendmsg(pkt_fd, &msg, 0); |
167 |
} |
} |
168 |
|
|
169 |
|
/* |
170 |
|
* Fetches a bootp packet, but doesn't remove it. |
171 |
|
* Returns: |
172 |
|
* 0 = Error |
173 |
|
* >0 = A packet of size "ret" is available for interface ifindex |
174 |
|
*/ |
175 |
int packet_peek(int *ifindex) |
int packet_peek(int *ifindex) |
176 |
{ |
{ |
177 |
struct sockaddr_ll sll; |
struct sockaddr_ll sll; |
184 |
ret = recvfrom(pkt_fd, &iph, sizeof(struct iphdr), |
ret = recvfrom(pkt_fd, &iph, sizeof(struct iphdr), |
185 |
MSG_PEEK, (struct sockaddr *)&sll, &sllen); |
MSG_PEEK, (struct sockaddr *)&sll, &sllen); |
186 |
if (ret == -1) |
if (ret == -1) |
187 |
return -1; |
return 0; |
188 |
|
|
189 |
if (sll.sll_family != AF_PACKET) |
if (sll.sll_family != AF_PACKET) |
190 |
goto discard_pkt; |
goto discard_pkt; |
194 |
|
|
195 |
*ifindex = sll.sll_ifindex; |
*ifindex = sll.sll_ifindex; |
196 |
|
|
197 |
return 0; |
return ret; |
198 |
|
|
199 |
discard_pkt: |
discard_pkt: |
200 |
packet_discard(); |
packet_discard(); |
214 |
/* |
/* |
215 |
* Receive a bootp packet. The options are listed in iov[1...iov_len]. |
* Receive a bootp packet. The options are listed in iov[1...iov_len]. |
216 |
* iov[0] must point to the bootp packet header. |
* iov[0] must point to the bootp packet header. |
217 |
|
* Returns: |
218 |
|
* 0 = Error, try again later |
219 |
|
* >0 = Size of packet |
220 |
*/ |
*/ |
221 |
int packet_recv(struct iovec *iov, int iov_len) |
int packet_recv(struct iovec *iov, int iov_len) |
222 |
{ |
{ |
236 |
ret = recvfrom(pkt_fd, &iph, sizeof(struct iphdr), |
ret = recvfrom(pkt_fd, &iph, sizeof(struct iphdr), |
237 |
MSG_PEEK, NULL, NULL); |
MSG_PEEK, NULL, NULL); |
238 |
if (ret == -1) |
if (ret == -1) |
239 |
return -1; |
return 0; |
240 |
|
|
241 |
if (iph.ihl < 5 || iph.version != IPVERSION) |
if (iph.ihl < 5 || iph.version != IPVERSION) |
242 |
goto discard_pkt; |
goto discard_pkt; |
256 |
if (ret == -1) |
if (ret == -1) |
257 |
goto free_pkt; |
goto free_pkt; |
258 |
|
|
259 |
DEBUG(("<- bytes %d ", ret)); |
dprintf("<- bytes %d ", ret); |
260 |
|
|
261 |
if (ip_checksum((uint16_t *) ip, ip->ihl) != 0) |
if (ip_checksum((uint16_t *) ip, ip->ihl) != 0) |
262 |
goto free_pkt; |
goto free_pkt; |
263 |
|
|
264 |
DEBUG(("\n ip src %s ", ntoa(ip->saddr))); |
dprintf("\n ip src %s ", ntoa(ip->saddr)); |
265 |
DEBUG(("dst %s ", ntoa(ip->daddr))); |
dprintf("dst %s ", ntoa(ip->daddr)); |
266 |
|
|
267 |
if (ntohs(ip->tot_len) > ret || ip->protocol != IPPROTO_UDP) |
if (ntohs(ip->tot_len) > ret || ip->protocol != IPPROTO_UDP) |
268 |
goto free_pkt; |
goto free_pkt; |
269 |
|
|
270 |
ret -= 4 * ip->ihl; |
ret -= 4 * ip->ihl; |
271 |
|
|
272 |
DEBUG(("\n udp src %d dst %d ", ntohs(udp->source), |
dprintf("\n udp src %d dst %d ", ntohs(udp->source), |
273 |
ntohs(udp->dest))); |
ntohs(udp->dest)); |
274 |
|
|
275 |
if (udp->source != htons(cfg_remote_port) || |
if (udp->source != htons(cfg_remote_port) || |
276 |
udp->dest != htons(cfg_local_port)) |
udp->dest != htons(cfg_local_port)) |
286 |
return ret; |
return ret; |
287 |
|
|
288 |
free_pkt: |
free_pkt: |
289 |
|
dprintf("freed\n"); |
290 |
free(ip); |
free(ip); |
291 |
return 0; |
return 0; |
292 |
|
|
293 |
discard_pkt: |
discard_pkt: |
294 |
DEBUG(("discarded\n")); |
dprintf("discarded\n"); |
295 |
packet_discard(); |
packet_discard(); |
296 |
return 0; |
return 0; |
297 |
} |
} |