Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * connection tracking event cache.
  3  */
  4 
  5 #ifndef _NF_CONNTRACK_ECACHE_H
  6 #define _NF_CONNTRACK_ECACHE_H
  7 #include <net/netfilter/nf_conntrack.h>
  8 
  9 #include <net/net_namespace.h>
 10 #include <net/netfilter/nf_conntrack_expect.h>
 11 #include <linux/netfilter/nf_conntrack_common.h>
 12 #include <linux/netfilter/nf_conntrack_tuple_common.h>
 13 #include <net/netfilter/nf_conntrack_extend.h>
 14 
 15 /* Connection tracking event types */
 16 enum ip_conntrack_events
 17 {
 18         IPCT_NEW                = 0,    /* new conntrack */
 19         IPCT_RELATED            = 1,    /* related conntrack */
 20         IPCT_DESTROY            = 2,    /* destroyed conntrack */
 21         IPCT_STATUS             = 3,    /* status has changed */
 22         IPCT_PROTOINFO          = 4,    /* protocol information has changed */
 23         IPCT_HELPER             = 5,    /* new helper has been set */
 24         IPCT_MARK               = 6,    /* new mark has been set */
 25         IPCT_NATSEQADJ          = 7,    /* NAT is doing sequence adjustment */
 26         IPCT_SECMARK            = 8,    /* new security mark has been set */
 27 };
 28 
 29 enum ip_conntrack_expect_events {
 30         IPEXP_NEW               = 0,    /* new expectation */
 31 };
 32 
 33 struct nf_conntrack_ecache {
 34         unsigned long cache;            /* bitops want long */
 35         unsigned long missed;           /* missed events */
 36         u32 pid;                        /* netlink pid of destroyer */
 37 };
 38 
 39 static inline struct nf_conntrack_ecache *
 40 nf_ct_ecache_find(const struct nf_conn *ct)
 41 {
 42         return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
 43 }
 44 
 45 static inline struct nf_conntrack_ecache *
 46 nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp)
 47 {
 48         struct net *net = nf_ct_net(ct);
 49 
 50         if (!net->ct.sysctl_events)
 51                 return NULL;
 52 
 53         return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
 54 };
 55 
 56 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 57 /* This structure is passed to event handler */
 58 struct nf_ct_event {
 59         struct nf_conn *ct;
 60         u32 pid;
 61         int report;
 62 };
 63 
 64 struct nf_ct_event_notifier {
 65         int (*fcn)(unsigned int events, struct nf_ct_event *item);
 66 };
 67 
 68 extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
 69 extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
 70 extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
 71 
 72 extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
 73 
 74 static inline void
 75 nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
 76 {
 77         struct nf_conntrack_ecache *e;
 78 
 79         if (nf_conntrack_event_cb == NULL)
 80                 return;
 81 
 82         e = nf_ct_ecache_find(ct);
 83         if (e == NULL)
 84                 return;
 85 
 86         set_bit(event, &e->cache);
 87 }
 88 
 89 static inline int
 90 nf_conntrack_eventmask_report(unsigned int eventmask,
 91                               struct nf_conn *ct,
 92                               u32 pid,
 93                               int report)
 94 {
 95         int ret = 0;
 96         struct net *net = nf_ct_net(ct);
 97         struct nf_ct_event_notifier *notify;
 98         struct nf_conntrack_ecache *e;
 99 
100         rcu_read_lock();
101         notify = rcu_dereference(nf_conntrack_event_cb);
102         if (notify == NULL)
103                 goto out_unlock;
104 
105         if (!net->ct.sysctl_events)
106                 goto out_unlock;
107 
108         e = nf_ct_ecache_find(ct);
109         if (e == NULL)
110                 goto out_unlock;
111 
112         if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
113                 struct nf_ct_event item = {
114                         .ct     = ct,
115                         .pid    = e->pid ? e->pid : pid,
116                         .report = report
117                 };
118                 /* This is a resent of a destroy event? If so, skip missed */
119                 unsigned long missed = e->pid ? 0 : e->missed;
120 
121                 ret = notify->fcn(eventmask | missed, &item);
122                 if (unlikely(ret < 0 || missed)) {
123                         spin_lock_bh(&ct->lock);
124                         if (ret < 0) {
125                                 /* This is a destroy event that has been
126                                  * triggered by a process, we store the PID
127                                  * to include it in the retransmission. */
128                                 if (eventmask & (1 << IPCT_DESTROY) &&
129                                     e->pid == 0 && pid != 0)
130                                         e->pid = pid;
131                                 else
132                                         e->missed |= eventmask;
133                         } else
134                                 e->missed &= ~missed;
135                         spin_unlock_bh(&ct->lock);
136                 }
137         }
138 out_unlock:
139         rcu_read_unlock();
140         return ret;
141 }
142 
143 static inline int
144 nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
145                           u32 pid, int report)
146 {
147         return nf_conntrack_eventmask_report(1 << event, ct, pid, report);
148 }
149 
150 static inline int
151 nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
152 {
153         return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
154 }
155 
156 struct nf_exp_event {
157         struct nf_conntrack_expect *exp;
158         u32 pid;
159         int report;
160 };
161 
162 struct nf_exp_event_notifier {
163         int (*fcn)(unsigned int events, struct nf_exp_event *item);
164 };
165 
166 extern struct nf_exp_event_notifier *nf_expect_event_cb;
167 extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
168 extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
169 
170 static inline void
171 nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
172                           struct nf_conntrack_expect *exp,
173                           u32 pid,
174                           int report)
175 {
176         struct net *net = nf_ct_exp_net(exp);
177         struct nf_exp_event_notifier *notify;
178 
179         rcu_read_lock();
180         notify = rcu_dereference(nf_expect_event_cb);
181         if (notify == NULL)
182                 goto out_unlock;
183 
184         if (!net->ct.sysctl_events)
185                 goto out_unlock;
186 
187         {
188                 struct nf_exp_event item = {
189                         .exp    = exp,
190                         .pid    = pid,
191                         .report = report
192                 };
193                 notify->fcn(1 << event, &item);
194         }
195 out_unlock:
196         rcu_read_unlock();
197 }
198 
199 static inline void
200 nf_ct_expect_event(enum ip_conntrack_expect_events event,
201                    struct nf_conntrack_expect *exp)
202 {
203         nf_ct_expect_event_report(event, exp, 0, 0);
204 }
205 
206 extern int nf_conntrack_ecache_init(struct net *net);
207 extern void nf_conntrack_ecache_fini(struct net *net);
208 
209 #else /* CONFIG_NF_CONNTRACK_EVENTS */
210 
211 static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
212                                             struct nf_conn *ct) {}
213 static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
214                                                 struct nf_conn *ct,
215                                                 u32 pid,
216                                                 int report) { return 0; }
217 static inline int nf_conntrack_event(enum ip_conntrack_events event,
218                                      struct nf_conn *ct) { return 0; }
219 static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
220                                             struct nf_conn *ct,
221                                             u32 pid,
222                                             int report) { return 0; }
223 static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
224 static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
225                                       struct nf_conntrack_expect *exp) {}
226 static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
227                                              struct nf_conntrack_expect *exp,
228                                              u32 pid,
229                                              int report) {}
230 
231 static inline int nf_conntrack_ecache_init(struct net *net)
232 {
233         return 0;
234 }
235 
236 static inline void nf_conntrack_ecache_fini(struct net *net)
237 {
238 }
239 #endif /* CONFIG_NF_CONNTRACK_EVENTS */
240 
241 #endif /*_NF_CONNTRACK_ECACHE_H*/
242 
243 
  This page was automatically generated by the LXR engine.