1 /* $NetBSD: mkarp.c,v 1.7 2008/07/21 13:36:59 lukem Exp $ */
4 * Copyright (c) 1984, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Sun Microsystems, Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
37 __COPYRIGHT("@(#) Copyright (c) 1984, 1993\
38 The Regents of the University of California. All rights reserved.");
43 static char sccsid
[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95";
45 __RCSID("$NetBSD: mkarp.c,v 1.7 2008/07/21 13:36:59 lukem Exp $");
50 * mkarp - set an arp table entry
53 #include <sys/param.h>
55 #include <sys/socket.h>
56 #include <sys/sysctl.h>
59 #include <net/if_dl.h>
60 #include <net/if_ether.h>
61 #include <net/if_types.h>
62 #include <net/route.h>
63 #include <netinet/in.h>
64 #include <netinet/if_inarp.h>
65 #include <arpa/inet.h>
79 /* Roundup the same way rt_xaddrs does */
81 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
83 int rtmsg(int, int, struct rt_msghdr
*, struct sockaddr_inarp
*,
84 struct sockaddr_dl
*);
86 struct rt_msghdr m_rtm
;
91 * Set an individual arp entry
94 mkarp(u_char
*haddr
, u_int32_t ipaddr
)
96 static struct sockaddr_inarp blank_sin
= {
97 sizeof(blank_sin
), AF_INET
, 0, { 0 }, { 0 }, 0, 0 };
98 static struct sockaddr_dl blank_sdl
= {
99 sizeof(blank_sdl
), AF_LINK
, 0, 0, 0, 0, 0, { 0 } };
101 struct sockaddr_inarp
*sin
;
102 struct sockaddr_dl
*sdl
;
103 struct rt_msghdr
*rtm
;
108 struct sockaddr_inarp sin_m
;
109 struct sockaddr_dl sdl_m
;
112 rtm
= &(m_rtmsg
.m_rtm
);
114 sdl_m
= blank_sdl
; /* struct copy */
115 sin_m
= blank_sin
; /* struct copy */
117 sin
->sin_addr
.s_addr
= ipaddr
;
120 endp
= ((caddr_t
)&sdl_m
) + sdl_m
.sdl_len
;
121 if (endp
> (p
+ ETHER_ADDR_LEN
))
122 endp
= p
+ ETHER_ADDR_LEN
;
127 sdl_m
.sdl_alen
= ETHER_ADDR_LEN
;
130 * We need to close and open the socket to prevent routing updates
131 * building up such that when we send our message we never see our
134 s
= socket(PF_ROUTE
, SOCK_RAW
, 0);
140 if (rtmsg(RTM_GET
, s
, rtm
, &sin_m
, &sdl_m
) < 0) {
147 sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
148 sdl
= (struct sockaddr_dl
*)(sin
->sin_len
+ (char *)sin
);
149 if (sin
->sin_addr
.s_addr
== sin_m
.sin_addr
.s_addr
) {
150 if (sdl
->sdl_family
== AF_LINK
&&
151 (rtm
->rtm_flags
& RTF_LLINFO
) &&
152 !(rtm
->rtm_flags
& RTF_GATEWAY
)) switch (sdl
->sdl_type
) {
153 case IFT_ETHER
: case IFT_FDDI
: case IFT_ISO88023
:
154 case IFT_ISO88024
: case IFT_ISO88025
: case IFT_ARCNET
:
158 (void)printf("set: can only proxy for %s\n", host
);
164 if (sdl
->sdl_family
!= AF_LINK
) {
166 (void)printf("cannot intuit interface index and type for %s\n",
172 sdl_m
.sdl_type
= sdl
->sdl_type
;
173 sdl_m
.sdl_index
= sdl
->sdl_index
;
174 result
= rtmsg(RTM_ADD
, s
, rtm
, &sin_m
, &sdl_m
);
180 rtmsg(int cmd
, int s
, struct rt_msghdr
*rtm
, struct sockaddr_inarp
*sin_m
,
181 struct sockaddr_dl
*sdl_m
)
190 rtm
= &m_rtmsg
.m_rtm
;
191 cp
= m_rtmsg
.m_space
;
196 (void)memset(&m_rtmsg
, 0, sizeof(m_rtmsg
));
197 rtm
->rtm_version
= RTM_VERSION
;
201 errx(1, "internal wrong cmd");
204 rtm
->rtm_addrs
|= RTA_GATEWAY
;
205 (void)gettimeofday(&tv
, 0);
206 rtm
->rtm_rmx
.rmx_expire
= tv
.tv_sec
+ 20 * 60;
207 rtm
->rtm_inits
= RTV_EXPIRE
;
208 rtm
->rtm_flags
|= (RTF_HOST
| RTF_STATIC
);
209 sin_m
->sin_other
= 0;
213 rtm
->rtm_addrs
|= RTA_DST
;
215 #define NEXTADDR(w, s) \
216 if (rtm->rtm_addrs & (w)) { \
217 (void)memcpy(cp, s, ((struct sockaddr *)s)->sa_len); \
218 cp += ROUNDUP(((struct sockaddr *)s)->sa_len);}
220 NEXTADDR(RTA_DST
, sin_m
);
221 NEXTADDR(RTA_GATEWAY
, sdl_m
);
223 rtm
->rtm_msglen
= cp
- (char *)&m_rtmsg
;
226 rtm
->rtm_seq
= ++seq
;
228 if ((rlen
= write(s
, (char *)&m_rtmsg
, l
)) < 0) {
229 if (errno
!= ESRCH
&& errno
!= EEXIST
) {
230 warn("writing to routing socket");
235 l
= read(s
, (char *)&m_rtmsg
, sizeof(m_rtmsg
));
236 } while (l
> 0 && (rtm
->rtm_seq
!= seq
|| rtm
->rtm_pid
!= pid
));
238 warn("read from routing socket");