blob: 0600d9908ab6ea30d176c6fe13ef725c4fa1866d [file] [log] [blame]
Dave Hudsondcd08fb2013-11-22 09:25:16 -06001/*
2 * sfe-cm.c
3 * Shortcut forwarding engine connection manager.
4 *
5 * XXX - fill in the appropriate GPL notice.
6 */
7#include <linux/module.h>
8#include <linux/sysfs.h>
9#include <linux/skbuff.h>
10#include <net/route.h>
11#include <linux/inetdevice.h>
12#include <linux/netfilter_bridge.h>
13#include <net/netfilter/nf_conntrack_acct.h>
14#include <net/netfilter/nf_conntrack_helper.h>
15#include <net/netfilter/nf_conntrack_zones.h>
16#include <net/netfilter/nf_conntrack_core.h>
17
18#include "sfe.h"
19#include "sfe_ipv4.h"
20
21/*
22 * Per-module structure.
23 */
24struct sfe_cm {
25 spinlock_t lock; /* Lock for SMP correctness */
26
27 /*
28 * Control state.
29 */
30 struct kobject *sys_sfe_cm; /* sysfs linkage */
31
32 /*
33 * Callback notifiers.
34 */
35 struct notifier_block dev_notifier;
36 /* Device notifier */
37 struct notifier_block inet_notifier;
38 /* IP notifier */
39};
40
41struct sfe_cm __sc;
42
43/*
44 * Expose the hook for the receive processing.
45 */
46extern int (*athrs_fast_nat_recv)(struct sk_buff *skb);
47
48/*
49 * Expose what should be a static flag in the TCP connection tracker.
50 */
51extern int nf_ct_tcp_no_window_check;
52
53/*
54 * sfe_cm_recv()
55 * Handle packet receives.
56 *
57 * Returns 1 if the packet is forwarded or 0 if it isn't.
58 */
59int sfe_cm_recv(struct sk_buff *skb)
60{
61 struct net_device *dev;
62#if (SFE_HOOK_ABOVE_BRIDGE)
63 struct in_device *in_dev;
64#endif
65
66 /*
67 * We know that for the vast majority of packets we need the transport
68 * layer header so we may as well start to fetch it now!
69 */
70 prefetch(skb->data + 32);
71 barrier();
72
73 dev = skb->dev;
74
75#if (SFE_HOOK_ABOVE_BRIDGE)
76 /*
77 * Does our input device support IP processing?
78 */
79 in_dev = (struct in_device *)dev->ip_ptr;
80 if (unlikely(!in_dev)) {
81 DEBUG_TRACE("no IP processing for device: %s\n", dev->name);
82 return 0;
83 }
84
85 /*
86 * Does it have an IP address? If it doesn't then we can't do anything
87 * interesting here!
88 */
89 if (unlikely(!in_dev->ifa_list)) {
90 DEBUG_TRACE("no IP address for device: %s\n", dev->name);
91 return 0;
92 }
93#endif
94
95 /*
96 * We're only interested in IP packets.
97 */
98 if (likely(htons(ETH_P_IP) == skb->protocol)) {
99 return sfe_ipv4_recv(dev, skb);
100 }
101
102 DEBUG_TRACE("not IP packet\n");
103 return 0;
104}
105
106/*
107 * sfe_cm_find_mac_addr()
108 * Find the MAC address for a given IPv4 address.
109 *
110 * Returns true if we find the MAC address, otherwise false.
111 *
112 * We look up the rtable entry for the address and, from its neighbour
113 * structure, obtain the hardware address. This means this function also
114 * works if the neighbours are routers too.
115 */
116static bool sfe_cm_find_mac_addr(uint32_t addr, uint8_t *mac_addr)
117{
118 struct neighbour *neigh;
119 struct rtable *rt;
120 struct dst_entry *dst;
121 struct net_device *dev;
122
123 /*
124 * Look up the rtable entry for the IP address then get the hardware
125 * address from its neighbour structure. This means this work when the
126 * neighbours are routers too.
127 */
128 rt = ip_route_output(&init_net, addr, 0, 0, 0);
129 if (unlikely(IS_ERR(rt))) {
130 return false;
131 }
132
133 dst = (struct dst_entry *)rt;
134
135 rcu_read_lock();
136 neigh = dst_get_neighbour_noref(dst);
137 if (unlikely(!neigh)) {
138 rcu_read_unlock();
139 dst_release(dst);
140 return false;
141 }
142
143 if (unlikely(!(neigh->nud_state & NUD_VALID))) {
144 rcu_read_unlock();
145 dst_release(dst);
146 return false;
147 }
148
149 dev = neigh->dev;
150 if (!dev) {
151 rcu_read_unlock();
152 dst_release(dst);
153 return false;
154 }
155
156 memcpy(mac_addr, neigh->ha, (size_t)dev->addr_len);
157 rcu_read_unlock();
158
159 dst_release(dst);
160
161 /*
162 * We're only interested in unicast MAC addresses - if it's not a unicast
163 * address then our IP address mustn't be unicast either.
164 */
165 if (is_multicast_ether_addr(mac_addr)) {
166 DEBUG_TRACE("MAC is non-unicast - ignoring\n");
167 return false;
168 }
169
170 return true;
171}
172
173/*
174 * sfe_cm_ipv4_post_routing_hook()
175 * Called for packets about to leave the box - either locally generated or forwarded from another interface
176 */
177static unsigned int sfe_cm_ipv4_post_routing_hook(unsigned int hooknum,
178 struct sk_buff *skb,
179 const struct net_device *in_unused,
180 const struct net_device *out,
181 int (*okfn)(struct sk_buff *))
182{
183 struct sfe_ipv4_create sic;
184 struct net_device *in;
185 struct nf_conn *ct;
186 enum ip_conntrack_info ctinfo;
187 struct net_device *src_dev;
188 struct net_device *dest_dev;
189 struct net_device *src_br_dev = NULL;
190 struct net_device *dest_br_dev = NULL;
191 struct nf_conntrack_tuple orig_tuple;
192 struct nf_conntrack_tuple reply_tuple;
193
194 /*
195 * Don't process broadcast or multicast packets.
196 */
197 if (unlikely(skb->pkt_type == PACKET_BROADCAST)) {
198 DEBUG_TRACE("broadcast, ignoring\n");
199 return NF_ACCEPT;
200 }
201 if (unlikely(skb->pkt_type == PACKET_MULTICAST)) {
202 DEBUG_TRACE("multicast, ignoring\n");
203 return NF_ACCEPT;
204 }
205
206 /*
207 * Don't process packets that are not being forwarded.
208 */
209 in = dev_get_by_index(&init_net, skb->skb_iif);
210 if (!in) {
211 DEBUG_TRACE("packet not forwarding\n");
212 return NF_ACCEPT;
213 }
214
215 /*
216 * Don't process packets with non-standard 802.3 MAC address sizes.
217 */
218 if (unlikely(in->addr_len != ETH_ALEN)) {
219 DEBUG_TRACE("in device: %s not 802.3 hw addr len: %u, ignoring\n",
220 in->name, (unsigned)in->addr_len);
221 goto done1;
222 }
223 if (unlikely(out->addr_len != ETH_ALEN)) {
224 DEBUG_TRACE("out device: %s not 802.3 hw addr len: %u, ignoring\n",
225 out->name, (unsigned)out->addr_len);
226 goto done1;
227 }
228
229 /*
230 * Don't process packets that aren't being tracked by conntrack.
231 */
232 ct = nf_ct_get(skb, &ctinfo);
233 if (unlikely(!ct)) {
234 DEBUG_TRACE("no conntrack connection, ignoring\n");
235 goto done1;
236 }
237
238 /*
239 * Don't process untracked connections.
240 */
241 if (unlikely(ct == &nf_conntrack_untracked)) {
242 DEBUG_TRACE("untracked connection\n");
243 goto done1;
244 }
245
246 /*
247 * Don't process connections that require support from a 'helper' (typically a NAT ALG).
248 */
249 if (unlikely(nfct_help(ct))) {
250 DEBUG_TRACE("connection has helper\n");
251 goto done1;
252 }
253
254 /*
255 * Look up the details of our connection in conntrack.
256 *
257 * Note that the data we get from conntrack is for the "ORIGINAL" direction
258 * but our packet may actually be in the "REPLY" direction.
259 */
260 orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
261 reply_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
262 sic.protocol = (int32_t)orig_tuple.dst.protonum;
263
264 /*
265 * Get addressing information, non-NAT first
266 */
267 sic.src_ip = (__be32)orig_tuple.src.u3.ip;
268 sic.dest_ip = (__be32)orig_tuple.dst.u3.ip;
269
270 /*
271 * NAT'ed addresses - note these are as seen from the 'reply' direction
272 * When NAT does not apply to this connection these will be identical to the above.
273 */
274 sic.src_ip_xlate = (__be32)reply_tuple.dst.u3.ip;
275 sic.dest_ip_xlate = (__be32)reply_tuple.src.u3.ip;
276
277 sic.flags = 0;
278
279 switch (sic.protocol) {
280 case IPPROTO_TCP:
281 sic.src_port = orig_tuple.src.u.tcp.port;
282 sic.dest_port = orig_tuple.dst.u.tcp.port;
283 sic.src_port_xlate = reply_tuple.dst.u.tcp.port;
284 sic.dest_port_xlate = reply_tuple.src.u.tcp.port;
285 sic.src_td_window_scale = ct->proto.tcp.seen[0].td_scale;
286 sic.src_td_max_window = ct->proto.tcp.seen[0].td_maxwin;
287 sic.src_td_end = ct->proto.tcp.seen[0].td_end;
288 sic.src_td_max_end = ct->proto.tcp.seen[0].td_maxend;
289 sic.dest_td_window_scale = ct->proto.tcp.seen[1].td_scale;
290 sic.dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin;
291 sic.dest_td_end = ct->proto.tcp.seen[1].td_end;
292 sic.dest_td_max_end = ct->proto.tcp.seen[1].td_maxend;
293 if (nf_ct_tcp_no_window_check
294 || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL)
295 || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) {
296 sic.flags |= SFE_IPV4_CREATE_FLAG_NO_SEQ_CHECK;
297 }
298
299 /*
300 * Don't try to manage a non-established connection.
301 */
302 if (!test_bit(IPS_ASSURED_BIT, &ct->status)) {
303 DEBUG_TRACE("non-established connection\n");
304 goto done1;
305 }
306
307 /*
308 * If the connection is shutting down do not manage it.
309 * state can not be SYN_SENT, SYN_RECV because connection is assured
310 * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE.
311 */
312 spin_lock_bh(&ct->lock);
313 if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) {
314 spin_unlock_bh(&ct->lock);
315 DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n",
316 ct->proto.tcp.state, &sic.src_ip, ntohs(sic.src_port),
317 &sic.dest_ip, ntohs(sic.dest_port));
318 goto done1;
319 }
320 spin_unlock_bh(&ct->lock);
321 break;
322
323 case IPPROTO_UDP:
324 sic.src_port = orig_tuple.src.u.udp.port;
325 sic.dest_port = orig_tuple.dst.u.udp.port;
326 sic.src_port_xlate = reply_tuple.dst.u.udp.port;
327 sic.dest_port_xlate = reply_tuple.src.u.udp.port;
328 break;
329
330 default:
331 DEBUG_TRACE("unhandled protocol %d\n", sic.protocol);
332 goto done1;
333 }
334
335 /*
336 * Get the MAC addresses that correspond to source and destination host addresses.
337 */
338 if (!sfe_cm_find_mac_addr(sic.src_ip, sic.src_mac)) {
339 DEBUG_TRACE("failed to find MAC address for src IP: %pI4\n", &sic.src_ip);
340 goto done1;
341 }
342
343 if (!sfe_cm_find_mac_addr(sic.src_ip_xlate, sic.src_mac_xlate)) {
344 DEBUG_TRACE("failed to find MAC address for xlate src IP: %pI4\n", &sic.src_ip_xlate);
345 goto done1;
346 }
347
348 /*
349 * Do dest now
350 */
351 if (!sfe_cm_find_mac_addr(sic.dest_ip, sic.dest_mac)) {
352 DEBUG_TRACE("failed to find MAC address for dest IP: %pI4\n", &sic.dest_ip);
353 goto done1;
354 }
355
356 if (!sfe_cm_find_mac_addr(sic.dest_ip_xlate, sic.dest_mac_xlate)) {
357 DEBUG_TRACE("failed to find MAC address for xlate dest IP: %pI4\n", &sic.dest_ip_xlate);
358 goto done1;
359 }
360
361 /*
362 * Get our device info. If we're dealing with the "reply" direction here then
363 * we'll need things swapped around.
364 */
365 if (ctinfo < IP_CT_IS_REPLY) {
366 src_dev = in;
367 dest_dev = (struct net_device *)out;
368 } else {
369 src_dev = (struct net_device *)out;
370 dest_dev = in;
371 }
372
373#if (!SFE_HOOK_ABOVE_BRIDGE)
374 /*
375 * Now our devices may actually be a bridge interface. If that's
376 * the case then we need to hunt down the underlying interface.
377 */
378 if (src_dev->priv_flags & IFF_EBRIDGE) {
379 src_br_dev = br_port_dev_get(src_dev, sic.src_mac);
380 if (!src_br_dev) {
381 DEBUG_TRACE("no port found on bridge\n");
382 goto done1;
383 }
384
385 src_dev = src_br_dev;
386 }
387
388 if (dest_dev->priv_flags & IFF_EBRIDGE) {
389 dest_br_dev = br_port_dev_get(dest_dev, sic.dest_mac_xlate);
390 if (!dest_br_dev) {
391 DEBUG_TRACE("no port found on bridge\n");
392 goto done2;
393 }
394
395 dest_dev = dest_br_dev;
396 }
397#else
398 /*
399 * Our devices may actually be part of a bridge interface. If that's
400 * the case then find the bridge interface instead.
401 */
402 if (src_dev->priv_flags & IFF_BRIDGE_PORT) {
403 src_br_dev = src_dev->master;
404 if (!src_br_dev) {
405 DEBUG_TRACE("no bridge found for: %s\n", src_dev->name);
406 goto done1;
407 }
408
409 dev_hold(src_br_dev);
410 src_dev = src_br_dev;
411 }
412
413 if (dest_dev->priv_flags & IFF_BRIDGE_PORT) {
414 dest_br_dev = dest_dev->master;
415 if (!dest_br_dev) {
416 DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name);
417 goto done2;
418 }
419
420 dev_hold(dest_br_dev);
421 dest_dev = dest_br_dev;
422 }
423#endif
424
425 sic.src_dev = src_dev;
426 sic.dest_dev = dest_dev;
427
428// XXX - these MTUs need handling correctly!
429 sic.src_mtu = 1500;
430 sic.dest_mtu = 1500;
431
432 sfe_ipv4_create_rule(&sic);
433
434 /*
435 * If we had bridge ports then release them too.
436 */
437 if (dest_br_dev) {
438 dev_put(dest_br_dev);
439 }
440
441done2:
442 if (src_br_dev) {
443 dev_put(src_br_dev);
444 }
445
446done1:
447 /*
448 * Release the interface on which this skb arrived
449 */
450 dev_put(in);
451
452 return NF_ACCEPT;
453}
454
455#ifdef CONFIG_NF_CONNTRACK_EVENTS
456/*
457 * sfe_cm_conntrack_event()
458 * Callback event invoked when a conntrack connection's state changes.
459 */
460static int sfe_cm_conntrack_event(unsigned int events, struct nf_ct_event *item)
461{
462 struct sfe_ipv4_destroy sid;
463 struct nf_conn *ct = item->ct;
464 struct nf_conntrack_tuple orig_tuple;
465
466 /*
467 * If we don't have a conntrack entry then we're done.
468 */
469 if (unlikely(!ct)) {
470 DEBUG_WARN("no ct in conntrack event callback\n");
471 return NOTIFY_DONE;
472 }
473
474 /*
475 * If this is an untracked connection then we can't have any state either.
476 */
477 if (unlikely(ct == &nf_conntrack_untracked)) {
478 DEBUG_TRACE("ignoring untracked conn\n");
479 return NOTIFY_DONE;
480 }
481
482 /*
483 * Ignore anything other than IPv4 connections.
484 */
485 if (unlikely(nf_ct_l3num(ct) != AF_INET)) {
486 DEBUG_TRACE("ignoring non-IPv4 conn\n");
487 return NOTIFY_DONE;
488 }
489
490 /*
491 * We're only interested in destroy events.
492 */
493 if (unlikely(!(events & (1 << IPCT_DESTROY)))) {
494 DEBUG_TRACE("ignoring non-destroy event\n");
495 return NOTIFY_DONE;
496 }
497
498 orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
499 sid.protocol = (int32_t)orig_tuple.dst.protonum;
500
501 /*
502 * Extract information from the conntrack connection. We're only interested
503 * in nominal connection information (i.e. we're ignoring any NAT information).
504 */
505 sid.src_ip = (__be32)orig_tuple.src.u3.ip;
506 sid.dest_ip = (__be32)orig_tuple.dst.u3.ip;
507
508 switch (sid.protocol) {
509 case IPPROTO_TCP:
510 sid.src_port = orig_tuple.src.u.tcp.port;
511 sid.dest_port = orig_tuple.dst.u.tcp.port;
512 break;
513
514 case IPPROTO_UDP:
515 sid.src_port = orig_tuple.src.u.udp.port;
516 sid.dest_port = orig_tuple.dst.u.udp.port;
517 break;
518
519 default:
520 DEBUG_TRACE("unhandled protocol: %d\n", sid.protocol);
521 return NOTIFY_DONE;
522 }
523
524
525 sfe_ipv4_destroy_rule(&sid);
526 return NOTIFY_DONE;
527}
528
529/*
530 * Netfilter conntrack event system to monitor connection tracking changes
531 */
532static struct nf_ct_event_notifier sfe_cm_conntrack_notifier = {
533 .fcn = sfe_cm_conntrack_event,
534};
535#endif
536
537/*
538 * Structure to establish a hook into the post routing netfilter point - this
539 * will pick up local outbound and packets going from one interface to another.
540 *
541 * Note: see include/linux/netfilter_ipv4.h for info related to priority levels.
542 * We want to examine packets after NAT translation and any ALG processing.
543 */
544static struct nf_hook_ops sfe_cm_ipv4_ops_post_routing[] __read_mostly = {
545 {
546 .hook = sfe_cm_ipv4_post_routing_hook,
547 .owner = THIS_MODULE,
548 .pf = PF_INET,
549 .hooknum = NF_INET_POST_ROUTING,
550 .priority = NF_IP_PRI_NAT_SRC + 1,
551 },
552};
553
554/*
555 * sfe_cm_sync_rule()
556 * Synchronize a connection's state.
557 */
558static void sfe_cm_sync_rule(struct sfe_ipv4_sync *sis)
559{
560 struct nf_conntrack_tuple_hash *h;
561 struct nf_conntrack_tuple tuple;
562 struct nf_conn *ct;
563 struct nf_conn_counter *acct;
564
565 /*
566 * Create a tuple so as to be able to look up a connection
567 */
568 memset(&tuple, 0, sizeof(tuple));
569 tuple.src.u3.ip = sis->src_ip;
570 tuple.src.u.all = (__be16)sis->src_port;
571 tuple.src.l3num = AF_INET;
572
573 tuple.dst.u3.ip = sis->dest_ip;
574 tuple.dst.dir = IP_CT_DIR_ORIGINAL;
575 tuple.dst.protonum = (uint8_t)sis->protocol;
576 tuple.dst.u.all = (__be16)sis->dest_port;
577
578 DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n",
579 (int)tuple.dst.protonum,
580 &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all),
581 &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all));
582
583 /*
584 * Look up conntrack connection
585 */
586 h = nf_conntrack_find_get(&init_net, NF_CT_DEFAULT_ZONE, &tuple);
587 if (unlikely(!h)) {
588 DEBUG_TRACE("no connection found\n");
589 return;
590 }
591
592 ct = nf_ct_tuplehash_to_ctrack(h);
593 NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct);
594
595 /*
596 * Only update if this is not a fixed timeout
597 */
598 if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
599 ct->timeout.expires += sis->delta_jiffies;
600 }
601
602 acct = nf_conn_acct_find(ct);
603 if (acct) {
604 spin_lock_bh(&ct->lock);
605 atomic64_add(sis->src_packet_count, &acct[IP_CT_DIR_ORIGINAL].packets);
606 atomic64_add(sis->src_byte_count, &acct[IP_CT_DIR_ORIGINAL].bytes);
607 atomic64_add(sis->dest_packet_count, &acct[IP_CT_DIR_REPLY].packets);
608 atomic64_add(sis->dest_byte_count, &acct[IP_CT_DIR_REPLY].bytes);
609 spin_unlock_bh(&ct->lock);
610 }
611
612 switch (sis->protocol) {
613 case IPPROTO_TCP:
614 spin_lock_bh(&ct->lock);
615 if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) {
616 ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window;
617 }
618 if ((int32_t)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) {
619 ct->proto.tcp.seen[0].td_end = sis->src_td_end;
620 }
621 if ((int32_t)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) {
622 ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end;
623 }
624 if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) {
625 ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window;
626 }
627 if ((int32_t)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) {
628 ct->proto.tcp.seen[1].td_end = sis->dest_td_end;
629 }
630 if ((int32_t)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) {
631 ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end;
632 }
633 spin_unlock_bh(&ct->lock);
634 break;
635 }
636
637 /*
638 * Release connection
639 */
640 nf_ct_put(ct);
641}
642
643/*
644 * sfe_cm_device_event()
645 */
646static int sfe_cm_device_event(struct notifier_block *this, unsigned long event, void *ptr)
647{
648 struct net_device *dev = (struct net_device *)ptr;
649
650 switch (event) {
651 case NETDEV_DOWN:
652 if (dev) {
653 sfe_ipv4_destroy_all_rules_for_dev(dev);
654 }
655 break;
656 }
657
658 return NOTIFY_DONE;
659}
660
661/*
662 * sfe_cm_inet_event()
663 */
664static int sfe_cm_inet_event(struct notifier_block *this, unsigned long event, void *ptr)
665{
666 struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
667 return sfe_cm_device_event(this, event, dev);
668}
669
670/*
671 * sfe_cm_init()
672 */
673static int __init sfe_cm_init(void)
674{
675 struct sfe_cm *sc = &__sc;
676 int result = -1;
677
678 DEBUG_INFO("SFE CM init\n");
679
680 /*
681 * Create sys/sfe_cm
682 */
683 sc->sys_sfe_cm = kobject_create_and_add("sfe_cm", NULL);
684 if (!sc->sys_sfe_cm) {
685 DEBUG_ERROR("failed to register sfe_cm\n");
686 goto exit1;
687 }
688
689 sc->dev_notifier.notifier_call = sfe_cm_device_event;
690 sc->dev_notifier.priority = 1;
691 register_netdevice_notifier(&sc->dev_notifier);
692
693 sc->inet_notifier.notifier_call = sfe_cm_inet_event;
694 sc->inet_notifier.priority = 1;
695 register_inetaddr_notifier(&sc->inet_notifier);
696
697 /*
698 * Register our netfilter hooks.
699 */
700 result = nf_register_hooks(sfe_cm_ipv4_ops_post_routing, ARRAY_SIZE(sfe_cm_ipv4_ops_post_routing));
701 if (result < 0) {
702 DEBUG_ERROR("can't register nf post routing hook: %d\n", result);
703 goto exit6;
704 }
705
706#ifdef CONFIG_NF_CONNTRACK_EVENTS
707 /*
708 * Register a notifier hook to get fast notifications of expired connections.
709 */
710 result = nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier);
711 if (result < 0) {
712 DEBUG_ERROR("can't register nf notifier hook: %d\n", result);
713 goto exit7;
714 }
715#endif
716
717 spin_lock_init(&sc->lock);
718
719 /*
720 * Hook the receive path in the network stack.
721 */
722 BUG_ON(athrs_fast_nat_recv != NULL);
723 RCU_INIT_POINTER(athrs_fast_nat_recv, sfe_cm_recv);
724
725 /*
726 * Hook the shortcut sync callback.
727 */
728 sfe_ipv4_register_sync_rule_callback(sfe_cm_sync_rule);
729 return 0;
730
731#ifdef CONFIG_NF_CONNTRACK_EVENTS
732exit7:
733#endif
734 nf_unregister_hooks(sfe_cm_ipv4_ops_post_routing, ARRAY_SIZE(sfe_cm_ipv4_ops_post_routing));
735
736exit6:
737 unregister_inetaddr_notifier(&sc->inet_notifier);
738 unregister_netdevice_notifier(&sc->dev_notifier);
739 kobject_put(sc->sys_sfe_cm);
740
741exit1:
742 return result;
743}
744
745/*
746 * sfe_cm_exit()
747 */
748static void __exit sfe_cm_exit(void)
749{
750 struct sfe_cm *sc = &__sc;
751
752 DEBUG_INFO("SFE CM exit\n");
753
754 /*
755 * Unregister our sync callback.
756 */
757 sfe_ipv4_register_sync_rule_callback(NULL);
758
759 /*
760 * Unregister our receive callback.
761 */
762 RCU_INIT_POINTER(athrs_fast_nat_recv, NULL);
763
764 /*
765 * Wait for all callbacks to complete.
766 */
767 rcu_barrier();
768
769 /*
770 * Destroy all connections.
771 */
772 sfe_ipv4_destroy_all_rules_for_dev(NULL);
773
774// XXX - this is where we need to unregister with any lower level offload services.
775
776#ifdef CONFIG_NF_CONNTRACK_EVENTS
777 nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier);
778
779#endif
780 nf_unregister_hooks(sfe_cm_ipv4_ops_post_routing, ARRAY_SIZE(sfe_cm_ipv4_ops_post_routing));
781
782 unregister_inetaddr_notifier(&sc->inet_notifier);
783 unregister_netdevice_notifier(&sc->dev_notifier);
784
785 kobject_put(sc->sys_sfe_cm);
786
787}
788
789module_init(sfe_cm_init)
790module_exit(sfe_cm_exit)
791
792MODULE_AUTHOR("Qualcomm Atheros Inc.");
793MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager");
794MODULE_LICENSE("GPL");
795