📄 fa_ipay.c
字号:
/* $Id: fa_ipay.c,v 1.3 2000/04/06 07:26:51 jm Exp $ * Foreign Agent - Ipay interface routines * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2000, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#ifdef INCLUDE_IPAY#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <errno.h>#include <ctype.h>#include <netinet/in.h>#include <arpa/inet.h>#include <assert.h>#include "binding.h"#include "debug.h"#include "ipay-msg.h"#include "fa.h"#include "fa_ipay.h"extern struct fa_config *config;extern struct bindingtable *bindings_hash;#define DEBUG_IPAY 'i'static void show_ipay_char(char *title, char *p){ int i; DEBUG(DEBUG_IPAY, "\t %s: ", title); for (i = 0; i < IPAY_CHAR_LEN; i++) { if (p[i] == '\0') break; if (isprint(p[i])) DEBUG(DEBUG_IPAY, "%c", p[i]); else DEBUG(DEBUG_IPAY, "<%u>", (unsigned int) p[i]); } DEBUG(DEBUG_IPAY, "\n");}static int ipay_check_len(int len, int expected){ if (len != expected) { DEBUG(DEBUG_IPAY, "\t - length mismatch (expected %i bytes)\n", expected); if (len < expected) { DEBUG(DEBUG_IPAY, "\t - too short - cannot parse\n"); return -1; } DEBUG(DEBUG_IPAY, "\t - ignoring extra bytes\n"); } return 0;}static void handle_purchase(int s, char *msg, int len){ struct ipay_purchase *pur; struct sockaddr_in addr; int res; DEBUG(DEBUG_IPAY, "\tpurchase message\n"); if (ipay_check_len(len, sizeof(struct ipay_purchase)) < 0) return; pur = (struct ipay_purchase *) msg; DEBUG(DEBUG_IPAY, "\t timeStamp: %u\n", ntohl(pur->timeStamp)); show_ipay_char("mnIdentifier", pur->mnIdentifier); show_ipay_char("faIdentifier", pur->faIdentifier); DEBUG(DEBUG_IPAY, "\t purchaseSerialNumber: %u\n", ntohl(pur->purchaseSerialNumber)); DEBUG(DEBUG_IPAY, "\t microPaymentUnit: %u\n", ntohl(pur->microPaymentUnit)); DEBUG(DEBUG_IPAY, "\t maxNumberOfUnits: %u\n", ntohl(pur->maxNumberOfUnits)); show_ipay_char("firstPayment", pur->firstPayment); DEBUG(DEBUG_IPAY, "\t timePrice: %u\n", ntohl(pur->timePrice)); DEBUG(DEBUG_IPAY, "\t bytePrice: %u\n", ntohl(pur->bytePrice)); show_ipay_char("signature", pur->signature); addr.sin_family = AF_INET; if (config->highest_FA) { DEBUG(DEBUG_IPAY, "\tforwarding message to AAAF\n"); addr.sin_addr = config->aaaf_addr; addr.sin_port = htons(config->aaaf_port); } else { DEBUG(DEBUG_IPAY, "\tforwarding message to upper FA\n"); addr.sin_addr = config->upper_fa_addr; addr.sin_port = htons(config->ipay_port); } DEBUG(DEBUG_IPAY, "\tsending %i bytes to %s:%i\n", len, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); res = sendto(s, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr)); if (res < 0) { DEBUG(DEBUG_IPAY, "\tsendto - %s\n", strerror(errno)); } else if (res != len) { DEBUG(DEBUG_IPAY, "\tsend only %i/%i bytes\n", res, len); }}static struct bindingentry *found_binding;static int fetch_iter(struct node *node, void *data){ struct bindingentry *entry = (struct bindingentry *) node; struct nai_data *key = (struct nai_data *) data; struct tunnel_data *t_data = (struct tunnel_data *) entry->data; if (key->len == t_data->mn_nai.len && t_data->mn_nai.nai != NULL && memcmp(key->nai, t_data->mn_nai.nai, key->len) == 0) { found_binding = entry; return 0; } return 1;}static int get_dest_mn_nai(IPAY_CHAR nai, struct sockaddr_in *addr){ struct nai_data key; key.len = 0; while (key.len < IPAY_CHAR_LEN && nai[key.len] != '\0') key.len++; key.nai = malloc(key.len); if (key.nai == NULL) { DEBUG(DEBUG_IPAY, "\tget_dest_mn_nai - malloc failed\n"); return -1; } memcpy(key.nai, nai, key.len); found_binding = NULL; hashtable_iterator(bindings_hash->hashtable, fetch_iter, &key); if (found_binding == NULL) return -1; addr->sin_family = AF_INET; addr->sin_addr = found_binding->lower_addr; addr->sin_port = htons(config->ipay_port); return 0;}static void handle_allowance(int s, char *msg, int len){ struct ipay_allowance *allow; struct sockaddr_in addr; int res; DEBUG(DEBUG_IPAY, "\tallowance message\n"); if (ipay_check_len(len, sizeof(struct ipay_allowance))) return; allow = (struct ipay_allowance *) msg; DEBUG(DEBUG_IPAY, "\t allowance: %u\n", ntohl(allow->allowance)); show_ipay_char("mnIdentifier", allow->mnIdentifier); DEBUG(DEBUG_IPAY, "\t timePrice: %u\n", ntohl(allow->timePrice)); DEBUG(DEBUG_IPAY, "\t bytePrice: %u\n", ntohl(allow->bytePrice)); DEBUG(DEBUG_IPAY, "\t apporovedNumberOfUnits: %u\n", ntohl(allow->approvedNumberOfUnits)); show_ipay_char("sessionKey", allow->sessionKey); show_ipay_char("signature", allow->signature); if (get_dest_mn_nai(allow->mnIdentifier, &addr) < 0) { DEBUG(DEBUG_IPAY, "\tno matching binding for MN NAI found\n"); return; } if (found_binding != NULL) { struct tunnel_data *t_data; t_data = (struct tunnel_data *) found_binding->data; if (!t_data->ipay_send_stats) { t_data->ipay_send_stats = 1; time(&t_data->ipay_last_stats); } } DEBUG(DEBUG_IPAY, "\tsending %i bytes to %s:%i\n", len, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); res = sendto(s, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr)); if (res < 0) { DEBUG(DEBUG_IPAY, "\tsendto - %s\n", strerror(errno)); } else if (res != len) { DEBUG(DEBUG_IPAY, "\tsend only %i/%i bytes\n", res, len); }}static void handle_please_pay_more(int s, char *msg, int len){ struct ipay_please_pay_more *pay; struct sockaddr_in addr; int res; DEBUG(DEBUG_IPAY, "\tplease pay more message\n"); if (ipay_check_len(len, sizeof(struct ipay_please_pay_more))) return; pay = (struct ipay_please_pay_more *) msg; show_ipay_char("mnIdentifier", pay->mnIdentifier); DEBUG(DEBUG_IPAY, "\t usedTime: %u\n", ntohl(pay->usedTime)); DEBUG(DEBUG_IPAY, "\t usedByte: %u\n", ntohl(pay->usedByte)); show_ipay_char("sessionKey", pay->sessionKey); show_ipay_char("signature", pay->signature); if (get_dest_mn_nai(pay->mnIdentifier, &addr) < 0) { DEBUG(DEBUG_IPAY, "\tno matching binding for MN NAI found\n"); return; } DEBUG(DEBUG_IPAY, "\tsending %i bytes to %s:%i\n", len, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); res = sendto(s, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr)); if (res < 0) { DEBUG(DEBUG_IPAY, "\tsendto - %s\n", strerror(errno)); } else if (res != len) { DEBUG(DEBUG_IPAY, "\tsend only %i/%i bytes\n", res, len); }}static void handle_micro_payment(int s, char *msg, int len){ struct ipay_micro_payment *pay; struct sockaddr_in addr; int res; DEBUG(DEBUG_IPAY, "\tmicro payment message\n"); if (ipay_check_len(len, sizeof(struct ipay_micro_payment)) < 0) return; pay = (struct ipay_micro_payment *) msg; show_ipay_char("mnIdentifier", pay->mnIdentifier); show_ipay_char("nextPayment", pay->nextPayment); addr.sin_family = AF_INET; if (config->highest_FA) { DEBUG(DEBUG_IPAY, "\tforwarding message to AAAF\n"); addr.sin_addr = config->aaaf_addr; addr.sin_port = htons(config->aaaf_port); } else { DEBUG(DEBUG_IPAY, "\tforwarding message to upper FA\n"); addr.sin_addr = config->upper_fa_addr; addr.sin_port = htons(config->ipay_port); } DEBUG(DEBUG_IPAY, "\tsending %i bytes to %s:%i\n", len, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); res = sendto(s, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr)); if (res < 0) { DEBUG(DEBUG_IPAY, "\tsendto - %s\n", strerror(errno)); } else if (res != len) { DEBUG(DEBUG_IPAY, "\tsend only %i/%i bytes\n", res, len); }}void handle_ipay(int s){ char msg[MAXMSG]; struct sockaddr_in from; int fromlen, len; IPAY_TYPE *type; DEBUG(DEBUG_IPAY, "Ipay message from socket %i\n", s); fromlen = sizeof(from); len = recvfrom(s, msg, MAXMSG, 0, (struct sockaddr *) &from, &fromlen); if (len < 0) { DEBUG(DEBUG_IPAY, "\trecvfrom failed - %s\n", strerror(errno)); return; } DEBUG(DEBUG_IPAY, "\t%i bytes from %s:%i\n", len, inet_ntoa(from.sin_addr), ntohs(from.sin_port)); if (len < sizeof(IPAY_TYPE)) { DEBUG(DEBUG_IPAY, "\ttoo short message - ignoring it\n"); return; } type = (IPAY_TYPE *) msg; DEBUG(DEBUG_IPAY, "\ttype=%i\n", ntohl(*type)); switch (ntohl(*type)) { case IPAY_MSG_PURCHASE: handle_purchase(s, msg, len); break; case IPAY_MSG_ALLOWANCE: handle_allowance(s, msg, len); break; case IPAY_MSG_PLEASE_PAY_MORE: handle_please_pay_more(s, msg, len); break; case IPAY_MSG_MICRO_PAYMENT: handle_micro_payment(s, msg, len); break; default: DEBUG(DEBUG_IPAY, "\tunknown message type - ignoring " "message\n"); break; }}static intsend_stats_iter(struct node *node, void *data){ struct ipay_capacity_used capa; struct bindingentry *binding; struct tunnel_data *t_data; struct sockaddr_in addr; int s, res; time_t now; time(&now); binding = (struct bindingentry *) node; t_data = (struct tunnel_data *) binding->data; assert(t_data != NULL); s = *((int *) data); if (!t_data->ipay_send_stats || !t_data->confirmed) return 1; /* send statistics */ memset(&capa, 0, sizeof(capa)); capa.type = htonl(IPAY_MSG_CAPACITY_USED); memcpy(capa.mnIdentifier, t_data->mn_nai.nai, t_data->mn_nai.len > IPAY_CHAR_LEN ? IPAY_CHAR_LEN : t_data->mn_nai.len); capa.timePrice = htonl(config->timePrice); capa.usedTime = htonl(now - t_data->ipay_last_stats); addr.sin_addr = config->aaaf_addr; addr.sin_port = htons(config->aaaf_port); DEBUG(DEBUG_IPAY, "sending capacity used to AAAF (%s:%i)\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); show_ipay_char("for MN", capa.mnIdentifier); res = sendto(s, &capa, sizeof(capa), 0, (struct sockaddr *) &addr, sizeof(addr)); if (res < 0) { DEBUG(DEBUG_IPAY, "\tsendto - %s\n", strerror(errno)); } else if (res != sizeof(capa)) { DEBUG(DEBUG_IPAY, "\tsend only %i/%i bytes\n", res, sizeof(capa)); } return 1;}/* do not send statistics more often than every 60 seconds */#define IPAY_STATS_INTERVAL 60void ipay_send_statistics(int s){ static time_t prev = 0; time_t now; if (!config->highest_FA) return; time(&now); if (prev > 0 && prev <= now && now < prev + IPAY_STATS_INTERVAL) return; prev = now; /* send statistics for every registered MN using Ipay */ hashtable_iterator(bindings_hash->hashtable, send_stats_iter, &s);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -