📄 db.c
字号:
/* * db and hash handle routines */#include <linux/slab.h> /* for kmalloc, kfree */#include "db.h"#include "util.h"#include "igmp_netfilter.h" /* TstIgmpSnpStatus */TstIgmpSnpStatus igmpsnp_global_stats;igmp_db_t * igmp_db_head;igmp_router_t igmp_router;static spinlock_t igmp_db_sem;void igmp_snooping_stats_reset_counter (void){ igmpsnp_global_stats.totol_pkt_rcvd = 0; igmpsnp_global_stats.valid_pkt_rcvd = 0; igmpsnp_global_stats.invalid_pkt_rcvd = 0; igmpsnp_global_stats.g_query_rcvd = 0; igmpsnp_global_stats.gs_query_rcvd = 0; igmpsnp_global_stats.leave_rcvd = 0; igmpsnp_global_stats.report_rcvd = 0; igmpsnp_global_stats.other_rcvd = 0; igmpsnp_global_stats.g_query_xmit = 0; igmpsnp_global_stats.gs_query_xmit = 0; igmpsnp_global_stats.leave_xmit = 0; igmpsnp_global_stats.report_xmit = 0;}void igmp_snooping_stats_init (int boot){ if (boot) { memset (&igmpsnp_global_stats, 0, sizeof(TstIgmpSnpStatus)); igmpsnp_global_stats.igmpsnp_enable = IGMPSNP_DFT_ENABLE; igmpsnp_global_stats.fastleave_enable = FASTLEAVE_DFT_ENABLE; igmpsnp_global_stats.querier_enable = QUERIER_DFT_ENABLE; igmpsnp_global_stats.debug_enable = DEBUG_DFT_ENABLE; } else { igmpsnp_global_stats.igmpsnp_enable = 0; igmp_snooping_stats_reset_counter (); } return;}void igmp_snooping_db_init (int boot){ igmp_router.addr = 0; igmp_router.port = 0; igmp_db_head = NULL; if (boot) { spin_lock_init (&igmp_db_sem); }}void igmp_db_copy_entry (igmp_db_t * to, igmp_db_t * from){ /* hnext and pnext are not copied */ to->gda = from->gda; to->life = from->life; to->port = from->port;}igmp_db_t * igmp_db_new_entry (__u32 gda, __u8 port, __u32 life){ igmp_db_t * ret; ret = (igmp_db_t *) kmalloc (sizeof (igmp_db_t), GFP_KERNEL); if (!ret) return NULL; ret->gda = gda; ret->life = life; ret->port = port; ret->hnext = NULL; ret->pnext = NULL; return ret;}int igmp_db_find_gda (igmp_db_t * ret, __u32 gda){ igmp_db_t *p; if (NULL == igmp_db_head) return 0; for (p = igmp_db_head; p; p = p->hnext) { if (gda == p->gda) { igmp_db_copy_entry (ret, p); return 1; } } return 0;}int igmp_db_find_entry (igmp_db_t * ret, __u32 gda, __u8 port){ igmp_db_t *head = NULL, *p; if (NULL == igmp_db_head) return 0; for (head = igmp_db_head; head; head = head->hnext) { if (head->gda == gda) { for (p = head; p; p = p->pnext) { if (p->port == port) { igmp_db_copy_entry (ret, p); return 1; } } break; /* no need to find another gda */ } } return 0;}int igmp_db_find_port (igmp_db_t * ret, __u8 port){ igmp_db_t *head = NULL, *p; if (NULL == igmp_db_head) return 0; for (head = igmp_db_head; head; head = head->hnext) { for (p = head; p; p = p->pnext) { if (p->port == port) { igmp_db_copy_entry (ret, p); return 1; } } } return 0;}int igmp_db_insert_entry (igmp_db_t * ins){ igmp_db_t *head, *p = NULL; int found = 0; if (NULL == ins) return 0; if (NULL == igmp_db_head) { igmp_db_head = ins; return 1; } if (igmp_db_find_entry (p, ins->gda, ins->port)) return 1; spin_lock (&igmp_db_sem); for (head = igmp_db_head; head; head = head->hnext) { if (head->gda == ins->gda) { found = 1; break; } } if (found) { /* gda exists */ ins->pnext = head->pnext; head->pnext = ins; } else { ins->hnext = igmp_db_head->hnext; igmp_db_head->hnext = ins; } spin_unlock (&igmp_db_sem); return 1;}int igmp_db_del_entry (igmp_db_t del){ igmp_db_t *head, *head_bak; igmp_db_t *p, *p_bak; char found; if (NULL == igmp_db_head || del.gda == 0) return 1; spin_lock (&igmp_db_sem); /* find gda head */ for (head = igmp_db_head, head_bak = NULL, found = 0; head; head_bak = head, head = head->hnext) { if (head->gda == del.gda) { found = 1; break; } } if (!found) /* gda not found */ return 1; /* find entry */ for (p = head, p_bak = NULL, found = 0; p; p_bak = p, p = p->pnext) { if (p->port == del.port){ found = 1; break; } } if (!found) /* entry not found */ return 1; /* entry found */ if (p_bak == NULL) { /* p is head */ if (head_bak == NULL) { /* head is igmp_db_head */ if (p->pnext) { /* other entries with same gda exist */ igmp_db_head = p->pnext; igmp_db_head->hnext = p->hnext; } else { igmp_db_head = p->hnext; } } else { if (p->pnext) { /* other entries with same gda exist */ p->pnext->hnext = head->hnext; head_bak->hnext = p->pnext; } else { head_bak->hnext = p->hnext; } } } else { /* p is leaf */ p_bak->pnext = p->pnext; } spin_unlock (&igmp_db_sem); kfree (p); return 1;}void igmp_db_del_all (void){ igmp_db_t *dh, *dh_prev = NULL; /* del_head */ igmp_db_t *d, *d_prev = NULL; /* del */ if (NULL == igmp_db_head) return;#define _DEL_SUB_ENTRIES() \ do { \ for (d_prev = dh, d = dh->pnext; d; d_prev = d, d = d->pnext) { \ if (d_prev == dh) /* first iteration */ \ continue; \ if (d_prev) \ kfree (d_prev); \ if (d->pnext == NULL) { /* last iteration */ \ kfree (d); \ break; \ } \ } \ } while (0) spin_lock (&igmp_db_sem); for (dh_prev = igmp_db_head, dh = igmp_db_head->hnext; dh; dh_prev = dh, dh = dh->hnext) { if (dh_prev == igmp_db_head) { /* first iteration */ _DEL_SUB_ENTRIES(); continue; } /* clean sub entries in the same gda */ _DEL_SUB_ENTRIES(); if (dh_prev) kfree (dh_prev); if (dh->hnext == NULL) { /* last iteration */ kfree (dh); break; } } kfree (igmp_db_head); igmp_db_head = NULL; spin_unlock (&igmp_db_sem);}int igmp_db_modify_life (igmp_db_t mod, __u32 life){ igmp_db_t *p; char found = 0; for (p = igmp_db_head; p; p = p->hnext) { if (p->gda == mod.gda) { found = 1; break; } } if (found) { for (; p; p = p->pnext) { if (p->port == mod.port) { p->life = life; return 1; } } } return 0;}void igmp_db_decrease_life (void){ igmp_db_t *head, *p; for (head = igmp_db_head; head; head = head->hnext) { for (p = head; p; p = p->pnext) { if (p->life > 0) { p->life -= 1; //printk("mod: g:%x,p:%d,l:%d\n", p->gda, p->port, p->life); } } }}int igmp_db_find_dead (igmp_db_t * ret){ igmp_db_t *head, *p; for (head = igmp_db_head; head; head = head->hnext) { for (p = head; p; p = p->pnext) { if ((p->life) == 0) { igmp_db_copy_entry (ret, p); return 1; } } } return 0;}void igmp_db_debug_print (char * title){ igmp_db_t *head, *p; int i = 0; if (NULL == title) printk (" debug print db =>\n"); else printk (" %s print db =>\n", title); for (head = igmp_db_head; head; head = head->hnext) { for (p = head; p; p = p->pnext) { ++i; printk (" %d. gda:%x port:%d life:%d\n", i, p->gda, p->port, p->life); } } if (0 == i) printk (" empty\n");}int get_mcast_groups_size (void){ igmp_db_t * p; int size = 0; for (p = igmp_db_head; p; p = p->hnext) { ++size; } return size;}unsigned long get_mcast_group_entry (int index){ igmp_db_t * p; int i = 0; /* starts from zero */ for (p = igmp_db_head; p; p = p->hnext, i++) { if (i == index) return (p->gda); } return 0UL;}unsigned long get_mcast_router (void){ return (igmp_router.addr);}unsigned char get_mcast_router_port (void){ return (igmp_router.port + 1);}#if 0/* * input: GDA address * function: count a hash key using 23 bits LSB of GDA * output: hash key */inline unsigned int gda_hash_f(struct in_addr gda){ return (unsigned int)((gda.s_addr&0x7FFFFF)%IGMPSNP_HASH_SZ);}/* * check the existence of porxy state given gda */proxy_state_t * report_proxy_lookup(proxy_state_t **phash, struct in_addr gda){ unsigned int key; proxy_state_t * p; key = gda_hash_f(gda); if (!phash[key]) return NULL; for (p=phash[key]; p!=NULL; p=p->next){ if (p->gda.s_addr == gda.s_addr) return p; } return NULL;}proxy_state_t * new_report_proxy_entry( struct in_addr addr, int qtype, int interval){ proxy_state_t * p; p = (proxy_state_t *)kmalloc(sizeof(proxy_state_t), GFP_KERNEL); if (!p) return NULL; p->gda.s_addr = addr.s_addr; switch (qtype) { case IGMPQ_GENERAL_QUERY: p->state = IGMPS_PROXY_REPORT; break; case IGMPQ_GS_QUERY: p->state = IGMPS_PROXY_GS_REPORT; break; case IGMPQ_LEAVE_GS_QUERY: p->state = IGMPQ_LEAVE_GS_QUERY; break; } p->proxy_int = interval; p->num_report = 0; p->num_gs_query = 0; p->tlist.expires = 0; p->lgs_port = 0; return p;}int report_proxy_add(proxy_state_t **phash, proxy_state_t * padd){ unsigned int key; if (report_proxy_lookup(phash, padd->gda) != NULL) return -1; key = gda_hash_f(padd->gda); padd->next = phash[key]? phash[key]: NULL; phash[key] = padd; return 1;}int report_proxy_del(proxy_state_t **phash, proxy_state_t * pdel){ proxy_state_t * p; unsigned int key; key = gda_hash_f(pdel->gda); if (!phash[key]) return -1; if (phash[key] == pdel) { phash[key] = pdel->next; kfree(pdel); return 1; } for (p=phash[key]; p!=NULL; p=p->next) if (p->next == pdel) break; p->next = pdel->next; kfree(pdel); return 1;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -