/* *------------------------------------------------------------------ * Copyright (c) 2017 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------ */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* sends msg to socket */ static int memif_msg_send_from_queue (memif_control_channel_t *cc) { struct msghdr mh = { 0 }; struct iovec iov[1]; char ctl[CMSG_SPACE (sizeof (int))]; int rv, err = MEMIF_ERR_SUCCESS; /* 0 */ memif_msg_queue_elt_t *e; /* Pick the first message */ e = TAILQ_FIRST (&cc->msg_queue); if (e == NULL) return MEMIF_ERR_SUCCESS; /* Construct the message */ iov[0].iov_base = (void *) &e->msg; iov[0].iov_len = sizeof (memif_msg_t); mh.msg_iov = iov; mh.msg_iovlen = 1; if (e->fd > 0) { struct cmsghdr *cmsg; memset (&ctl, 0, sizeof (ctl)); mh.msg_control = ctl; mh.msg_controllen = sizeof (ctl); cmsg = CMSG_FIRSTHDR (&mh); cmsg->cmsg_len = CMSG_LEN (sizeof (int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; memcpy (CMSG_DATA (cmsg), &e->fd, sizeof (int)); } rv = sendmsg (cc->fd, &mh, 0); if (rv < 0) err = memif_syscall_error_handler (errno); DBG ("Message type %u sent", e->msg.type); /* If sent successfully, remove the msg from queue */ if (err == MEMIF_ERR_SUCCESS) { TAILQ_REMOVE (&cc->msg_queue, e, next); cc->sock->args.free (e); } return err; } static memif_msg_queue_elt_t * memif_msg_enq (memif_control_channel_t *cc) { memif_msg_queue_elt_t *e; e = cc->sock->args.alloc (sizeof (*e)); if (e == NULL) return NULL; e->fd = -1; TAILQ_INSERT_TAIL (&cc->msg_queue, e, next); return e; } static int memif_msg_enq_hello (memif_control_channel_t *cc) { memif_msg_hello_t *h; memif_msg_queue_elt_t *e = memif_msg_enq (cc); if (e == NULL) return MEMIF_ERR_NOMEM; e->msg.type = MEMIF_MSG_TYPE_HELLO; h = &e->msg.hello; h->min_version = MEMIF_VERSION; h->max_version = MEMIF_VERSION; h->max_s2m_ring = MEMIF_MAX_S2M_RING; h->max_m2s_ring = MEMIF_MAX_M2S_RING; h->max_region = MEMIF_MAX_REGION; h->max_log2_ring_size = MEMIF_MAX_LOG2_RING_SIZE; strlcpy ((char *) h->name, (char *) cc->sock->args.app_name, sizeof (h->name)); return MEMIF_ERR_SUCCESS; } /* response from memif master - master is ready to handle next message */ static int memif_msg_enq_ack (memif_control_channel_t *cc) { memif_msg_queue_elt_t *e = memif_msg_enq (cc); if (e == NULL) return MEMIF_ERR_NOMEM; e->msg.type = MEMIF_MSG_TYPE_ACK; e->fd = -1; return MEMIF_ERR_SUCCESS; /* 0 */ } /* send id and secret (optional) for interface identification */ static int memif_msg_enq_init (memif_control_channel_t *cc) { memif_msg_queue_elt_t *e = memif_msg_enq (cc); if (e == NULL) return MEMIF_ERR_NOMEM; memif_msg_init_t *i = &e->msg.init; e->msg.type = MEMIF_MSG_TYPE_INIT; e->fd = -1; i->version = MEMIF_VERSION; i->id = cc->conn->args.interface_id; i->mode = cc->conn->args.mode; strlcpy ((char *) i->name, (char *) cc->sock->args.app_name, sizeof (i->name)); if (strlen ((char *) cc->conn->args.secret) > 0) strlcpy ((char *) i->secret, (char *) cc->conn->args.secret, sizeof (i->secret)); return MEMIF_ERR_SUCCESS; /* 0 */ } /* send information about region specified by region_index */ static int memif_msg_enq_add_region (memif_control_channel_t *cc, uint8_t region_index) { memif_region_t *mr = &cc->conn->regions[region_index]; memif_msg_queue_elt_t *e = memif_msg_enq (cc); if (e == NULL) return MEMIF_ERR_NOMEM; memif_msg_add_region_t *ar = &e->msg.add_region; e->msg.type = MEMIF_MSG_TYPE_ADD_REGION; e->fd = mr->fd; ar->index = region_index; ar->size = mr->region_size; return MEMIF_ERR_SUCCESS; /* 0 */ } /* send information about ring specified by direction (S2M | M2S) and index */ static int memif_msg_enq_add_ring (memif_control_channel_t *cc, uint8_t index, uint8_t dir) { memif_msg_queue_elt_t *e = memif_msg_enq (cc); if (e == NULL) return MEMIF_ERR_NOMEM; memif_msg_add_ring_t *ar = &e->msg.add_ring; e->msg.type = MEMIF_MSG_TYPE_ADD_RING; /* TODO: support multiple rings */ memif_queue_t *mq; if (dir == MEMIF_RING_M2S) mq = &cc->conn->rx_queues[index]; else mq = &cc->conn->tx_queues[index]; e->fd = mq->int_fd; ar->index = index; ar->offset = mq->offset; ar->region = mq->region; ar->log2_ring_size = mq->log2_ring_size; ar->flags = (dir == MEMIF_RING_S2M) ? MEMIF_MSG_ADD_RING_FLAG_S2M : 0; ar->private_hdr_size = 0; return MEMIF_ERR_SUCCESS; /* 0 */ } /* used as connection request from slave */ static int memif_msg_enq_connect (memif_control_channel_t *cc) { memif_msg_queue_elt_t *e = memif_msg_enq (cc); if (e == NULL) return MEMIF_ERR_NOMEM; memif_msg_connect_t *cm = &e->msg.connect; e->msg.type = MEMIF_MSG_TYPE_CONNECT; e->fd = -1; strlcpy ((char *) cm->if_name, (char *) cc->conn->args.interface_name, sizeof (cm->if_name)); return MEMIF_ERR_SUCCESS; /* 0 */ } /* used as confirmation of connection by master */ static int memif_msg_enq_connected (memif_control_channel_t *cc) { memif_msg_queue_elt_t *e = memif_msg_enq (cc); if (e == NULL) return MEMIF_ERR_NOMEM; memif_msg_connected_t *cm = &e->msg.connected; e->msg.type = MEMIF_MSG_TYPE_CONNECTED; e->fd = -1; strlcpy ((char *) cm->if_name, (char *) cc->conn->args.interface_name, sizeof (cm->if_name)); return MEMIF_ERR_SUCCESS; /* 0 */ } int memif_msg_enq_disconnect (memif_control_channel_t *cc, uint8_t *err_string, uint32_t err_code) { memif_msg_queue_elt_t *e; e = cc->sock->args.alloc (sizeof (*e)); if (e == NULL) return MEMIF_ERR_NOMEM; e->fd = -1; /* Insert disconenct message at the top of the msg queue */ TAILQ_INSERT_HEAD (&cc->msg_queue, e, next); memif_msg_disconnect_t *d = &e->msg.disconnect; e->msg.type = MEMIF_MSG_TYPE_DISCONNECT; d->code = err_code; uint16_t l = sizeof (d->string); if (l > 96) { DBG ("Disconnect string too long. Sending the first %ld characters.", sizeof (d->string) - 1); } strlcpy ((char *) d->string, (char *) err_string, sizeof (d->string)); return MEMIF_ERR_SUCCESS; } static int memif_msg_parse_hello (memif_control_channel_t *cc, memif_msg_t *msg) { memif_msg_hello_t *h = &msg->hello; memif_connection_t *c = cc->conn; if (msg->hello.min_version > MEMIF_VERSION || msg->hello.max_version < MEMIF_VERSION) { DBG ("incompatible protocol version"); return MEMIF_ERR_PROTO; } c->run_args.num_s2m_rings = memif_min (h->max_s2m_ring + 1, c->args.num_s2m_rings); c->run_args.num_m2s_rings = memif_min (h->max_m2s_ring + 1, c->args.num_m2s_rings); c->run_args.log2_ring_size = memif_min (h->max_log2_ring_size, c->args.log2_ring_size); c->run_args.buffer_size = c->args.buffer_size; strlcpy ((char *) c->remote_name, (char *) h->name, sizeof (c->remote_name)); return MEMIF_ERR_SUCCESS; /* 0 */ } /* handle interface identification (id, secret (optional)) */ static int memif_msg_parse_init (memif_control_channel_t *cc, memif_msg_t *msg) { memif_msg_init_t *i = &msg->init; memif_connection_t *c = NULL; uint8_t err_string[96]; memset (err_string, 0, sizeof (char) * 96); int err = MEMIF_ERR_SUCCESS; /* 0 */ /* Check compatible meimf version */ if (i->version != MEMIF_VERSION) { DBG ("MEMIF_VER_ERR"); memif_msg_enq_disconnect (cc, MEMIF_VER_ERR, 0); return MEMIF_ERR_PROTO; } /* Find endpoint on the socket */ TAILQ_FOREACH (c, &cc->sock->master_interfaces, next) { /* Match interface id */ if (c->args.interface_id != i->id) continue; /* If control channel is present, interface is connected (or connecting) */ if (c->control_channel != NULL) { memif_msg_enq_disconnect (cc, "Already connected", 0); return MEMIF_ERR_ALRCONN; } /* Verify secret */ if (c->args.secret[0] != '\0') { if (strncmp ((char *) c->args.secret, (char *) i->secret, 24) != 0) { memif_msg_enq_disconnect (cc, "Incorrect secret", 0); return MEMIF_ERR_SECRET; } } /* A
## This file is part of Scapy
## See http://www.secdev.org/projects/scapy for more informations
## Copyright (C) Philippe Biondi <phil@secdev.org>
## This program is published under a GPLv2 license

"""
Cisco Skinny protocol.
"""

from scapy.packet import *
from scapy.fields import *
from scapy.layers.inet import TCP

# shamelessly ripped from Ethereal dissector
skinny_messages = { 
# Station -> Callmanager
  0x0000: "KeepAliveMessage",
  0x0001: "RegisterMessage",
  0x0002: "IpPortMessage",
  0x0003: "KeypadButtonMessage",
  0x0004: "EnblocCallMessage",
  0x0005: "StimulusMessage",
  0x0006: "OffHookMessage",
  0x0007: "OnHookMessage",
  0x0008: "HookFlashMessage",
  0x0009: "ForwardStatReqMessage",
  0x000A: "SpeedDialStatReqMessage",
  0x000B: "LineStatReqMessage",
  0x000C: "ConfigStatReqMessage",
  0x000D: "TimeDateReqMessage",
  0x000E: "ButtonTemplateReqMessage",
  0x000F: "VersionReqMessage",
  0x0010: "CapabilitiesResMessage",
  0x0011: "MediaPortListMessage",
  0x0012: "ServerReqMessage",
  0x0020: "AlarmMessage",
  0x0021: "MulticastMediaReceptionAck",
  0x0022: "OpenReceiveChannelAck",
  0x0023: "ConnectionStatisticsRes",
  0x0024: "OffHookWithCgpnMessage",
  0x0025: "SoftKeySetReqMessage",
  0x0026: "SoftKeyEventMessage",
  0x0027: "UnregisterMessage",
  0x0028: "SoftKeyTemplateReqMessage",
  0x0029: "RegisterTokenReq",
  0x002A: "MediaTransmissionFailure",
  0x002B: "HeadsetStatusMessage",
  0x002C: "MediaResourceNotification",
  0x002D: "RegisterAvailableLinesMessage",
  0x002E: "DeviceToUserDataMessage",
  0x002F: "DeviceToUserDataResponseMessage",
  0x0030: "UpdateCapabilitiesMessage",
  0x0031: "OpenMultiMediaReceiveChannelAckMessage",
  0x0032: "ClearConferenceMessage",
  0x0033: "ServiceURLStatReqMessage",
  0x0034: "FeatureStatReqMessage",
  0x0035: "CreateConferenceResMessage",
  0x0036: "DeleteConferenceResMessage",
  0x0037: "ModifyConferenceResMessage",
  0x0038: "AddParticipantResMessage",
  0x0039: "AuditConferenceResMessage",
  0x0040: "AuditParticipantResMessage",
  0x0041: "DeviceToUserDataVersion1Message",
# Callmanager -> Station */
  0x0081: "RegisterAckMessage",
  0x0082: "StartToneMessage",
  0x0083: "StopToneMessage",