@@ -137,10 +137,10 @@ static void *myzalloc(size_t size)
137137}
138138
139139static int myrecvfrom6 (int sockfd , void * buf , size_t * buflen , int flags ,
140- struct in6_addr * addr , uint32_t * ifindex )
140+ struct in6_addr * addr , uint32_t * ifindex , int * hoplimit )
141141{
142142 struct sockaddr_in6 sin6 ;
143- unsigned char cbuf [CMSG_SPACE (sizeof (struct in6_pktinfo ))];
143+ unsigned char cbuf [2 * CMSG_SPACE (sizeof (struct in6_pktinfo ))];
144144 struct iovec iovec ;
145145 struct msghdr msghdr ;
146146 struct cmsghdr * cmsghdr ;
@@ -168,13 +168,26 @@ static int myrecvfrom6(int sockfd, void *buf, size_t *buflen, int flags,
168168 * ifindex = sin6 .sin6_scope_id ;
169169 for (cmsghdr = CMSG_FIRSTHDR (& msghdr ); cmsghdr ;
170170 cmsghdr = CMSG_NXTHDR (& msghdr , cmsghdr )) {
171- if (cmsghdr -> cmsg_level == IPPROTO_IPV6 &&
172- cmsghdr -> cmsg_type == IPV6_PKTINFO &&
173- cmsghdr -> cmsg_len == CMSG_LEN (sizeof (struct in6_pktinfo ))) {
174- struct in6_pktinfo * pktinfo ;
171+ if (cmsghdr -> cmsg_level != IPPROTO_IPV6 )
172+ continue ;
173+
174+ switch (cmsghdr -> cmsg_type ) {
175+ case IPV6_PKTINFO :
176+ if (cmsghdr -> cmsg_len == CMSG_LEN (sizeof (struct in6_pktinfo ))) {
177+ struct in6_pktinfo * pktinfo ;
178+
179+ pktinfo = (struct in6_pktinfo * ) CMSG_DATA (cmsghdr );
180+ * ifindex = pktinfo -> ipi6_ifindex ;
181+ }
182+ break ;
183+ case IPV6_HOPLIMIT :
184+ if (cmsghdr -> cmsg_len == CMSG_LEN (sizeof (int ))) {
185+ int * val ;
175186
176- pktinfo = (struct in6_pktinfo * ) CMSG_DATA (cmsghdr );
177- * ifindex = pktinfo -> ipi6_ifindex ;
187+ val = (int * ) CMSG_DATA (cmsghdr );
188+ * hoplimit = * val ;
189+ }
190+ break ;
178191 }
179192 }
180193 * addr = sin6 .sin6_addr ;
@@ -249,6 +262,15 @@ static int ndp_sock_open(struct ndp *ndp)
249262 goto close_sock ;
250263 }
251264
265+ val = 1 ;
266+ ret = setsockopt (sock , IPPROTO_IPV6 , IPV6_RECVHOPLIMIT ,
267+ & val , sizeof (val ));
268+ if (ret == -1 ) {
269+ err (ndp , "Failed to setsockopt IPV6_RECVHOPLIMIT,." );
270+ err = - errno ;
271+ goto close_sock ;
272+ }
273+
252274 ndp -> sock = sock ;
253275 return 0 ;
254276close_sock :
@@ -291,6 +313,7 @@ struct ndp_msg {
291313 size_t len ;
292314 struct in6_addr addrto ;
293315 uint32_t ifindex ;
316+ int hoplimit ;
294317 struct icmp6_hdr * icmp6_hdr ;
295318 unsigned char * opts_start ; /* pointer to buf at the
296319 place where opts start */
@@ -1697,13 +1720,19 @@ static int ndp_sock_recv(struct ndp *ndp)
16971720
16981721 len = ndp_msg_payload_maxlen (msg );
16991722 err = myrecvfrom6 (ndp -> sock , msg -> buf , & len , 0 ,
1700- & msg -> addrto , & msg -> ifindex );
1723+ & msg -> addrto , & msg -> ifindex , & msg -> hoplimit );
17011724 if (err ) {
17021725 err (ndp , "Failed to receive message" );
17031726 goto free_msg ;
17041727 }
1705- dbg (ndp , "rcvd from: %s, ifindex: %u" ,
1706- str_in6_addr (& msg -> addrto ), msg -> ifindex );
1728+ dbg (ndp , "rcvd from: %s, ifindex: %u, hoplimit: %d" ,
1729+ str_in6_addr (& msg -> addrto ), msg -> ifindex , msg -> hoplimit );
1730+
1731+ if (msg -> hoplimit != 255 ) {
1732+ warn (ndp , "ignoring packet with bad hop limit (%d)" , msg -> hoplimit );
1733+ err = 0 ;
1734+ goto free_msg ;
1735+ }
17071736
17081737 if (len < sizeof (* msg -> icmp6_hdr )) {
17091738 warn (ndp , "rcvd icmp6 packet too short (%luB)" , len );
0 commit comments