/* Handles incoming LE_ARP_RESPONSE frames.
 * Returns < 0 for serious error
 */
static int handle_arp_rsp(struct ctrl_frame *frame, int size)
{
        int sizeoftlvs, msglen, retval;
        char buff[MAX_CTRL_FRAME];
        struct atmlec_msg *msg;
        
        if (frame->header.lec_id != htons(lec_params.c14_lec_id)) {
                diag(COMPONENT, DIAG_DEBUG, "Wrong lec_id, ignoring\n");
                return 0;
        }

        sizeoftlvs = size - sizeof(struct ctrl_frame);
        msglen = sizeof(struct atmlec_msg) + sizeoftlvs;
        msg = (struct atmlec_msg *)buff;
        memset(msg, 0, msglen);
        
        msg->type = l_arp_update;
        memcpy(msg->content.normal.mac_addr, frame->target_lan_dst.mac, ETH_ALEN);
        memcpy(msg->content.normal.atm_addr, frame->target_atm_addr, ATM_ESA_LEN);
        msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
        msg->sizeoftlvs = sizeoftlvs;
        if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);

        retval = msg_to_kernel(msg, msglen);

        return retval;
}
Example #2
0
File: main.c Project: ebichu/dd-wrt
/* Tell kernel the parameters this ELAN has.
 * Returns < 0 for serious error
 */
static int config_kernel(void)
{
        struct atmlec_msg msg;

        memset(&msg, 0, sizeof(struct atmlec_msg));
        msg.type = l_config;
        msg.content.config.maximum_unknown_frame_count = lec_params.c10_max_unknown_frames;
        msg.content.config.max_unknown_frame_time = lec_params.c11_max_unknown_frame_time;
        msg.content.config.max_retry_count = lec_params.c13_max_retry_count;
        msg.content.config.aging_time = lec_params.c17_aging_time;
        msg.content.config.forward_delay_time = lec_params.c18_forward_delay_time;
        msg.content.config.arp_response_time = lec_params.c20_le_arp_response_time;
        msg.content.config.flush_timeout = lec_params.c21_flush_timeout;
        msg.content.config.path_switching_delay = lec_params.c22_path_switching_delay;
        msg.content.config.lane_version = (lec_params.c29_v2_capable) ? 2 : 1;
	msg.content.config.mtu = maxmtu2itfmtu(lec_params.c3_max_frame_size);
	msg.content.config.is_proxy = lec_params.c4_proxy_flag;

        if (msg_to_kernel(&msg, sizeof(struct atmlec_msg)) < 0) {
                diag(COMPONENT, DIAG_ERROR, "Could not tell kernel ELAN parameters");
                return -1;
        }

        return 0;
}
/* Handles incoming LE_NARP_REQUESTS frames.
 * Mandatory only in LANEv2. If we are LANEv1, we'll just ignore these.
 * See LANEv2, 7.1.31-35 LE_NARP_REQUEST/RESPONSE.
 * For no-source, i.e. no source ATM address, we remove the LE_ARP cache entry.
 * If the source is non-zero, we first remove the entry
 * and then add the new entry in the LE_ARP cache.
 * Returns < 0 for serious error.
 */
static int handle_narp_req(struct ctrl_frame *frame, int size)
{
        int sizeoftlvs, no_source = 0, retval;
        struct atmlec_msg *msg;
        unsigned char empty[ATM_ESA_LEN];

        if (frame->header.lec_id == htons(lec_params.c14_lec_id) ||
            lec_params.c29_v2_capable == 0) {
                diag(COMPONENT, DIAG_DEBUG, "Ignoring LE_NARP_REQUEST\n");
                return 0;
        }

        memset(empty, 0, ATM_ESA_LEN);
        if (memcmp(empty, frame->src_atm_addr, ATM_ESA_LEN) == 0)
                no_source = 1;

        sizeoftlvs = size - sizeof(struct ctrl_frame);
        msg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + sizeoftlvs);
        if (msg == NULL) return -1;
        memset(msg, 0, sizeof(struct atmlec_msg));
        msg->type = l_narp_req;
        memcpy(msg->content.normal.mac_addr, frame->src_lan_dst.mac, ETH_ALEN);
        memcpy(msg->content.normal.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
        msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
        msg->content.normal.no_source_le_narp = no_source;
        msg->sizeoftlvs = sizeoftlvs;
        if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);
        retval = msg_to_kernel(msg, sizeof(struct atmlec_msg) + sizeoftlvs);
        
        free(msg);
        
        return retval;
}
Example #4
0
static void delete_addr(unsigned char *atm_addr)
{
        struct atmlec_msg msg;

        msg.type = l_addr_delete;
        memcpy(msg.content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
        msg_to_kernel(&msg, sizeof(struct atmlec_msg));

        return;
}
/* Handles incoming LE_TOPOLOGY_REQUEST frames.
 * Returns < 0 for serious error
 */
static int handle_topo_req(struct ctrl_frame *frame)
{
        struct atmlec_msg msg;

        memset(&msg, 0, sizeof(struct atmlec_msg));
        msg.type = l_topology_change;
        if (frame->header.flags & htons(TOPO_CHANGE))
                msg.content.normal.flag = 1;

        return(msg_to_kernel(&msg, sizeof(struct atmlec_msg)));
}
Example #6
0
File: main.c Project: ebichu/dd-wrt
/* Tells kernel what our LEC_ID is.
 * Returns < 0 for serisous error
 */
static int set_lec_id(uint16_t lec_id)
{
        struct atmlec_msg msg;

        memset(&msg, 0, sizeof(struct atmlec_msg));
        msg.type = l_set_lecid;
        msg.content.normal.flag = lec_id;
        if (msg_to_kernel(&msg, sizeof(struct atmlec_msg)) < 0) {
                diag(COMPONENT, DIAG_ERROR, "Could not tell kernel LEC_ID");
                return -1;
        }

        return 0;
}
/* Helper for handle_le_arp_req.
 * If the target_lan_dst was not our MAC address, try to
 * see if the bridging table in the kernel knows about it.
 * Returns < 0 for serious error
 */
static int check_bridge(struct ctrl_frame *frame, int size)
{
        struct atmlec_msg msg;

        if (lec_params.c4_proxy_flag == 0)
                return 0;

        memset(&msg, 0, sizeof(struct atmlec_msg));
        msg.type = l_should_bridge;
        memcpy(msg.content.proxy.mac_addr, frame->target_lan_dst.mac, ETH_ALEN);
        memcpy(msg.content.proxy.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
        msg.content.proxy.tran_id = frame->header.tran_id;
        msg.content.proxy.lec_id = frame->header.lec_id;

        return msg_to_kernel(&msg, sizeof(struct atmlec_msg));
}
/* Handle incoming LE_FLUSH_RESPONSE frames.
 */
static void handle_flush_rsp(struct ctrl_frame *f)
{
        struct atmlec_msg msg;

        if (f->header.lec_id != htons(lec_params.c14_lec_id)) {
                diag(COMPONENT, DIAG_DEBUG, "Wrong lec_id, ignoring\n");
                return;
        }

        memset(&msg, 0, sizeof(struct atmlec_msg));
        msg.type = l_flush_complete;
        msg.content.normal.flag = ntohl(f->header.tran_id);
        msg_to_kernel(&msg, sizeof(struct atmlec_msg));
        
        return;
}
/* Handles incoming LE_ARP_REQ and targetless LE_ARP_REQ.
 * See LANEv2, 7.1.5 and 7.1.30
 * Returns < 0 for serious error
 */
static int handle_le_arp_req(struct ctrl_frame *frame, int size)
{
        int sizeoftlvs, sizeofrsp, retval;
        struct ctrl_frame *rsp;
        struct atmlec_msg *msg;

        if (frame->header.lec_id == htons(lec_params.c14_lec_id)) {
                diag(COMPONENT, DIAG_DEBUG, "Ignoring own LE_ARP_REQUEST\n");
                return 0;
        }

        retval = 0;
        if (frame->target_lan_dst.tag == htons(LAN_DST_MAC_ADDR)) {
                if (memcmp(frame->target_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN) != 0)
                        return (check_bridge(frame, size)); /* target was not us */
                sizeofrsp = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs;
                rsp = (struct ctrl_frame *)malloc(sizeofrsp);
                if (rsp == NULL) return 0;
                memcpy(rsp, frame, sizeof(struct ctrl_frame));
                rsp->header.opcode = htons(LE_ARP_RSP);
                memcpy(rsp->target_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN);
                rsp->num_tlvs = lec_params.num_tlvs;
                if (lec_params.num_tlvs > 0)
                        memcpy(rsp + 1, lec_params.tlvs, lec_params.sizeoftlvs);

                retval = send_frame(lec_params.ctrl_direct, rsp, sizeofrsp);
                free(rsp);
        } else if (frame->target_lan_dst.tag == htons(LAN_DST_NOT_PRESENT) &&
                   lec_params.c29_v2_capable) {
                sizeoftlvs = size - sizeof(struct ctrl_frame);
                msg = (struct atmlec_msg *)malloc(sizeof(struct atmlec_msg) + sizeoftlvs);
                if (msg == NULL) return -1;
                memset(msg, 0, sizeof(struct atmlec_msg));
                msg->type = l_arp_update;
                memcpy(msg->content.normal.mac_addr, frame->src_lan_dst.mac, ETH_ALEN);
                memcpy(msg->content.normal.atm_addr, frame->src_atm_addr, ATM_ESA_LEN);
                msg->content.normal.flag = (frame->header.flags & REMOTE_ADDRESS) ? 1 : 0;
                msg->content.normal.targetless_le_arp = 1;
                msg->sizeoftlvs = sizeoftlvs;
                if (sizeoftlvs > 0) memcpy(msg + 1, frame + 1, sizeoftlvs);

                retval = msg_to_kernel(msg, sizeof(struct atmlec_msg) + sizeoftlvs);
                free(msg);
        }
        
        return retval;
}