@@ -131,6 +131,20 @@ hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen)
131131 return hwaddr_buffer ;
132132}
133133
134+ static void
135+ in_len2mask (in_addr_t * mask , unsigned int len )
136+ {
137+ unsigned int i ;
138+ uint8_t * p ;
139+
140+ p = (uint8_t * )mask ;
141+ memset (mask , 0 , sizeof (* mask ));
142+ for (i = 0 ; i < len / 8 ; i ++ )
143+ p [i ] = 0xff ;
144+ if (len % 8 )
145+ p [i ] = (uint8_t )((0xff00 >> (len % 8 )) & 0xff );
146+ }
147+
134148/* Because fgetln does not return C strings, we cannot use
135149 * functions such as strsep and friends to extract words.
136150 * This is no bad thing this below code handles extracting words
@@ -160,32 +174,108 @@ get_word(char **s, const char *e)
160174}
161175
162176static void
163- free_prefix (__unused void * arg , __unused const void * key , __unused size_t len ,
164- void * val )
177+ pm_init (pstore_t * store ) {
178+ unsigned int plen ;
179+ pbucket_t * bucket ;
180+
181+ for (plen = 0 ; plen <= PREFIX_MAX_LEN ; plen ++ ) {
182+ bucket = & store -> buckets [plen ];
183+ bucket -> plen = plen ;
184+ in_len2mask (& bucket -> mask , bucket -> plen );
185+ bucket -> set = false;
186+ paction_map_init (& bucket -> prefixes );
187+ }
188+ }
189+
190+ static void
191+ pm_cleanup (pstore_t * store )
165192{
193+ unsigned int plen ;
194+ pbucket_t * bucket ;
166195
167- free (val );
196+ for (plen = 0 ; plen <= PREFIX_MAX_LEN ; plen ++ ) {
197+ bucket = & store -> buckets [plen ];
198+ paction_map_cleanup (& bucket -> prefixes );
199+ bucket -> set = false;
200+ }
168201}
169202
170- static void free_prefixes (lpm_t * * prefixes )
203+ static bool
204+ pm_anyset (pstore_t * store )
171205{
206+ unsigned int plen ;
172207
173- if (* prefixes == NULL )
174- return ;
208+ for (plen = 0 ; plen < PREFIX_MAX_LEN ; plen ++ ) {
209+ if (store -> buckets [plen ].set )
210+ return true;
211+ }
212+ return false;
213+ }
214+
215+ static paction_t *
216+ pm_get (pstore_t * store , in_addr_t ip , unsigned int plen )
217+ {
218+ pbucket_t * bucket ;
219+ paction_map_itr itr ;
220+
221+ bucket = & store -> buckets [plen ];
222+ if (!bucket -> set )
223+ return NULL ;
224+
225+ itr = paction_map_get (& bucket -> prefixes , ip );
226+ if (paction_map_is_end (itr ))
227+ return NULL ;
228+
229+ return itr .data -> val ;
230+ }
231+
232+ static paction_t *
233+ pm_lookup (pstore_t * store , in_addr_t ip )
234+ {
235+ paction_map_itr itr ;
236+ int plen = PREFIX_MAX_LEN ;
237+ pbucket_t * bucket ;
238+ in_addr_t addr ;
239+
240+ for (plen = PREFIX_MAX_LEN ; plen >= 0 ; plen -- ) {
241+ bucket = & store -> buckets [plen ];
242+ if (!bucket -> set ) {
243+ continue ;
244+ }
175245
176- lpm_clear (* prefixes , free_prefix , NULL );
177- free (* prefixes );
178- * prefixes = NULL ;
246+ addr = ip & bucket -> mask ;
247+ itr = paction_map_get (& bucket -> prefixes , addr );
248+ if (!paction_map_is_end (itr ))
249+ return itr .data -> val ;
250+ }
251+
252+ return NULL ;
253+ }
254+
255+ static int
256+ pm_insert (pstore_t * store , in_addr_t ip , unsigned int plen , paction_t * pa )
257+ {
258+ pbucket_t * bucket ;
259+ paction_map_itr itr ;
260+
261+ bucket = & store -> buckets [plen ];
262+ ip &= bucket -> mask ;
263+ itr = paction_map_insert (& store -> buckets [plen ].prefixes , ip , pa );
264+ if (paction_map_is_end (itr ))
265+ return -1 ;
266+
267+ bucket -> set = true;
268+ return 0 ;
179269}
180270
181271static void
182272free_config (struct ctx * ctx )
183273{
184274 struct interface * ifp ;
185275
186- free_prefixes (& ctx -> prefixes );
276+ pm_cleanup (& ctx -> pstore );
187277 TAILQ_FOREACH (ifp , & ctx -> ifaces , next ) {
188- free_prefixes (& ifp -> prefixes );
278+ pm_cleanup (& ifp -> pstore );
189279 }
190280}
191281
@@ -198,12 +288,12 @@ load_config(struct ctx *ctx)
198288 char * buf , * cmd , * match , * hwaddr , * bp , * p , * e , * r , act ;
199289 size_t buf_len ;
200290 ssize_t len ;
201- struct prefix * pp ;
202291 long plen ;
203292 int in_interface ;
204293 struct in_addr ina ;
205294 struct interface * ifp ;
206- lpm_t * prefixes ;
295+ paction_t * pa ;
296+ pstore_t * pstore ;
207297
208298 if (stat (ctx -> cffile , & st ) == -1 ) {
209299 free_config (ctx );
@@ -308,45 +398,30 @@ load_config(struct ctx *ctx)
308398 }
309399 }
310400 }
311-
312- if (ifp != NULL ) {
313- if (ifp -> prefixes == NULL )
314- ifp -> prefixes = lpm_create ();
315- prefixes = ifp -> prefixes ;
316- } else {
317- if (ctx -> prefixes == NULL )
318- ctx -> prefixes = lpm_create ();
319- prefixes = ctx -> prefixes ;
320- }
321- if (prefixes == NULL ) {
322- syslog (LOG_ERR , "lpm_create: %m" );
323- goto err ;
324- }
401+ pstore = ifp != NULL ? & ifp -> pstore : & ctx -> pstore ;
325402
326403 /* Check if we have already added the prefix,
327404 * overwrite it if we have. */
328- pp = lpm_lookup_prefix (prefixes , & ina .s_addr ,
329- sizeof (ina .s_addr ), (unsigned int )plen );
330- if (pp == NULL ) {
331- pp = malloc (sizeof (* pp ));
332- if (pp == NULL )
405+ pa = pm_get (pstore , ina .s_addr , (unsigned int )plen );
406+ if (pa == NULL ) {
407+ pa = malloc (sizeof (* pa ));
408+ if (pa == NULL )
333409 goto err ;
334- pp -> ip = ina .s_addr ;
335- pp -> plen = (unsigned int )plen ;
336- if (lpm_insert (prefixes , & pp -> ip , sizeof (pp -> ip ),
337- pp -> plen , pp ) == -1 )
410+ pa -> ip = ina .s_addr ;
411+ pa -> plen = (unsigned int )plen ;
412+ if (pm_insert (pstore , pa -> ip , pa -> plen , pa ) == -1 )
338413 {
339- syslog (LOG_ERR , "lpm_insert : %m" );
340- free (pp );
414+ syslog (LOG_ERR , "pm_insert : %m" );
415+ free (pa );
341416 goto err ;
342417 }
343418 }
344419
345- pp -> action = act ;
420+ pa -> action = act ;
346421 if (hwaddr == NULL )
347- pp -> hwlen = 0 ;
422+ pa -> hwlen = 0 ;
348423 else
349- pp -> hwlen = hwaddr_aton (pp -> hwaddr , hwaddr );
424+ pa -> hwlen = hwaddr_aton (pa -> hwaddr , hwaddr );
350425 }
351426
352427 error = 0 ;
@@ -361,25 +436,22 @@ static int
361436proxy (struct ctx * ctx , struct interface * ifp , in_addr_t ip ,
362437 const uint8_t * * hw , size_t * hwlen )
363438{
364- struct prefix * pp ;
439+ paction_t * pa ;
365440
366441 if (load_config (ctx ) == -1 )
367442 return -1 ;
368443
369- if (ifp -> prefixes != NULL )
370- pp = lpm_lookup (ifp -> prefixes , & ip , sizeof (ip ));
371- else
372- pp = NULL ;
373- if (pp == NULL && ctx -> prefixes != NULL )
374- pp = lpm_lookup (ctx -> prefixes , & ip , sizeof (ip ));
375- if (pp == NULL )
444+ pa = pm_lookup (& ifp -> pstore , ip );
445+ if (pa == NULL )
446+ pa = pm_lookup (& ctx -> pstore , ip );
447+ if (pa == NULL )
376448 return PARPD_IGNORE ;
377449
378- if (pp -> action ) {
379- * hw = pp -> hwaddr ;
380- * hwlen = pp -> hwlen ;
450+ if (pa -> action ) {
451+ * hw = pa -> hwaddr ;
452+ * hwlen = pa -> hwlen ;
381453 }
382- return pp -> action ;
454+ return pa -> action ;
383455}
384456
385457#define ARP_LEN \
@@ -419,7 +491,6 @@ expire_ipaddr(void *arg)
419491 struct ipaddr * ipa = arg ;
420492
421493 ipaddr_map_erase (& ipa -> ifp -> ipaddrs , ipa -> ipaddr );
422- free (ipa );
423494}
424495
425496/* Checks an incoming ARP message to see if we should proxy for it. */
@@ -645,6 +716,7 @@ discover_interfaces(struct ctx *ctx, int argc, char * const *argv)
645716 memcpy (ifp -> hwaddr , sll -> sll_addr , ifp -> hwlen );
646717#endif
647718
719+ pm_init (& ifp -> pstore );
648720 vt_init (& ifp -> ipaddrs );
649721
650722 TAILQ_INSERT_TAIL (& ctx -> ifaces , ifp , next );
@@ -722,6 +794,7 @@ main(int argc, char **argv)
722794
723795 opt = EXIT_FAILURE ;
724796
797+ pm_init (& ctx .pstore );
725798 TAILQ_INIT (& ctx .ifaces );
726799 discover_interfaces (& ctx , argc , argv );
727800
@@ -747,7 +820,7 @@ main(int argc, char **argv)
747820
748821 i = 0 ;
749822 TAILQ_FOREACH (ifp , & ctx .ifaces , next ) {
750- if (ctx .prefixes == NULL && ifp -> prefixes == NULL )
823+ if (! pm_anyset ( & ctx .pstore ) && ! pm_anyset ( & ifp -> pstore ) )
751824 continue ;
752825
753826 if ((ifp -> fd = bpf_open_arp (ifp )) == -1 ) {
@@ -783,15 +856,8 @@ main(int argc, char **argv)
783856#ifdef SANITIZE_MEMORY
784857 free_config (& ctx );
785858 while ((ifp = TAILQ_FIRST (& ctx .ifaces )) != NULL ) {
786- ipaddr_map_itr itr ;
787-
788859 TAILQ_REMOVE (& ctx .ifaces , ifp , next );
789- for (itr = ipaddr_map_first (& ifp -> ipaddrs );
790- !ipaddr_map_is_end (itr );
791- itr = ipaddr_map_next (itr ))
792- {
793- free (itr .data -> val );
794- }
860+ ipaddr_map_cleanup (& ifp -> ipaddrs );
795861 if (ifp -> fd != -1 )
796862 close (ifp -> fd );
797863 free (ifp -> buffer );
0 commit comments