@@ -89,6 +89,25 @@ ip6t_ext_hdr(u8 nexthdr)
89
89
(nexthdr == IPPROTO_DSTOPTS ) );
90
90
}
91
91
92
+ static unsigned long ifname_compare (const char * _a , const char * _b ,
93
+ const unsigned char * _mask )
94
+ {
95
+ const unsigned long * a = (const unsigned long * )_a ;
96
+ const unsigned long * b = (const unsigned long * )_b ;
97
+ const unsigned long * mask = (const unsigned long * )_mask ;
98
+ unsigned long ret ;
99
+
100
+ ret = (a [0 ] ^ b [0 ]) & mask [0 ];
101
+ if (IFNAMSIZ > sizeof (unsigned long ))
102
+ ret |= (a [1 ] ^ b [1 ]) & mask [1 ];
103
+ if (IFNAMSIZ > 2 * sizeof (unsigned long ))
104
+ ret |= (a [2 ] ^ b [2 ]) & mask [2 ];
105
+ if (IFNAMSIZ > 3 * sizeof (unsigned long ))
106
+ ret |= (a [3 ] ^ b [3 ]) & mask [3 ];
107
+ BUILD_BUG_ON (IFNAMSIZ > 4 * sizeof (unsigned long ));
108
+ return ret ;
109
+ }
110
+
92
111
/* Returns whether matches rule or not. */
93
112
/* Performance critical - called for every packet */
94
113
static inline bool
@@ -99,7 +118,6 @@ ip6_packet_match(const struct sk_buff *skb,
99
118
unsigned int * protoff ,
100
119
int * fragoff , bool * hotdrop )
101
120
{
102
- size_t i ;
103
121
unsigned long ret ;
104
122
const struct ipv6hdr * ipv6 = ipv6_hdr (skb );
105
123
@@ -120,12 +138,7 @@ ip6_packet_match(const struct sk_buff *skb,
120
138
return false;
121
139
}
122
140
123
- /* Look for ifname matches; this should unroll nicely. */
124
- for (i = 0 , ret = 0 ; i < IFNAMSIZ /sizeof (unsigned long ); i ++ ) {
125
- ret |= (((const unsigned long * )indev )[i ]
126
- ^ ((const unsigned long * )ip6info -> iniface )[i ])
127
- & ((const unsigned long * )ip6info -> iniface_mask )[i ];
128
- }
141
+ ret = ifname_compare (indev , ip6info -> iniface , ip6info -> iniface_mask );
129
142
130
143
if (FWINV (ret != 0 , IP6T_INV_VIA_IN )) {
131
144
dprintf ("VIA in mismatch (%s vs %s).%s\n" ,
@@ -134,11 +147,7 @@ ip6_packet_match(const struct sk_buff *skb,
134
147
return false;
135
148
}
136
149
137
- for (i = 0 , ret = 0 ; i < IFNAMSIZ /sizeof (unsigned long ); i ++ ) {
138
- ret |= (((const unsigned long * )outdev )[i ]
139
- ^ ((const unsigned long * )ip6info -> outiface )[i ])
140
- & ((const unsigned long * )ip6info -> outiface_mask )[i ];
141
- }
150
+ ret = ifname_compare (outdev , ip6info -> outiface , ip6info -> outiface_mask );
142
151
143
152
if (FWINV (ret != 0 , IP6T_INV_VIA_OUT )) {
144
153
dprintf ("VIA out mismatch (%s vs %s).%s\n" ,
0 commit comments