if (debug & DEBUG_L1OIP_MSG)
printk(KERN_DEBUG "%s: resetting timer\n", __func__);
/* drop if we have no remote ip or port */ if (!hc->sin_remote.sin_addr.s_addr || !hc->sin_remote.sin_port) { if (debug & DEBUG_L1OIP_MSG)
printk(KERN_DEBUG "%s: dropping frame, because remote " "IP is not set.\n", __func__); return len;
}
/* assemble frame */
*p++ = (L1OIP_VERSION << 6) /* version and coding */
| (hc->pri ? 0x20 : 0x00) /* type */
| (hc->id ? 0x10 : 0x00) /* id */
| localcodec; if (hc->id) {
*p++ = hc->id >> 24; /* id */
*p++ = hc->id >> 16;
*p++ = hc->id >> 8;
*p++ = hc->id;
}
*p++ = 0x00 + channel; /* m-flag, channel */
*p++ = timebase >> 8; /* time base */
*p++ = timebase;
if (buf && len) { /* add data to frame */ if (localcodec == 1 && ulaw)
l1oip_ulaw_to_alaw(buf, len, p); elseif (localcodec == 2 && !ulaw)
l1oip_alaw_to_ulaw(buf, len, p); elseif (localcodec == 3)
len = l1oip_law_to_4bit(buf, len, p,
&hc->chan[channel].codecstate); else
memcpy(p, buf, len);
}
len += p - frame;
/* check for socket in safe condition */
spin_lock(&hc->socket_lock); if (!hc->socket) {
spin_unlock(&hc->socket_lock); return0;
} /* seize socket */
socket = hc->socket;
hc->socket = NULL;
spin_unlock(&hc->socket_lock); /* send packet */ if (debug & DEBUG_L1OIP_MSG)
printk(KERN_DEBUG "%s: sending packet to socket (len " "= %d)\n", __func__, len);
hc->sendiov.iov_base = frame;
hc->sendiov.iov_len = len;
len = kernel_sendmsg(socket, &hc->sendmsg, &hc->sendiov, 1, len); /* give socket back */
hc->socket = socket; /* no locking required */
/* check packet_id */ if (packet_id) { if (!hc->id) {
printk(KERN_WARNING "%s: packet error - packet has id " "0x%x, but we have not\n", __func__, packet_id); return;
} if (len < 4) {
printk(KERN_WARNING "%s: packet error - packet too " "short for ID value\n", __func__); return;
}
packet_id = (*buf++) << 24;
packet_id += (*buf++) << 16;
packet_id += (*buf++) << 8;
packet_id += (*buf++);
len -= 4;
if (packet_id != hc->id) {
printk(KERN_WARNING "%s: packet error - ID mismatch, " "got 0x%x, we 0x%x\n",
__func__, packet_id, hc->id); return;
}
} else { if (hc->id) {
printk(KERN_WARNING "%s: packet error - packet has no " "ID, but we have\n", __func__); return;
}
}
multiframe: if (len < 1) {
printk(KERN_WARNING "%s: packet error - packet too short, " "channel expected at position %d.\n",
__func__, len-len_start + 1); return;
}
/* get channel and multiframe flag */
channel = *buf & 0x7f;
m = *buf >> 7;
buf++;
len--;
/* check length on multiframe */ if (m) { if (len < 1) {
printk(KERN_WARNING "%s: packet error - packet too " "short, length expected at position %d.\n",
__func__, len_start - len - 1); return;
}
mlen = *buf++;
len--; if (mlen == 0)
mlen = 256; if (len < mlen + 3) {
printk(KERN_WARNING "%s: packet error - length %d at " "position %d exceeds total length %d.\n",
__func__, mlen, len_start-len - 1, len_start); return;
} if (len == mlen + 3) {
printk(KERN_WARNING "%s: packet error - length %d at " "position %d will not allow additional " "packet.\n",
__func__, mlen, len_start-len + 1); return;
}
} else
mlen = len - 2; /* single frame, subtract timebase */
if (len < 2) {
printk(KERN_WARNING "%s: packet error - packet too short, time " "base expected at position %d.\n",
__func__, len-len_start + 1); return;
}
/* get time base */
timebase = (*buf++) << 8;
timebase |= (*buf++);
len -= 2;
/* if inactive, we send up a PH_ACTIVATE and activate */ if (!test_bit(FLG_ACTIVE, &dch->Flags)) { if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
printk(KERN_DEBUG "%s: interface become active due to " "received packet\n", __func__);
test_and_set_bit(FLG_ACTIVE, &dch->Flags);
_queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
NULL, GFP_ATOMIC);
}
/* bind to incoming port */ if (socket->ops->bind(socket, (struct sockaddr *)&hc->sin_local, sizeof(hc->sin_local))) {
printk(KERN_ERR "%s: Failed to bind socket to port %d.\n",
__func__, hc->localport);
ret = -EINVAL; goto fail;
}
/* check sk */ if (socket->sk == NULL) {
printk(KERN_ERR "%s: socket->sk == NULL\n", __func__);
ret = -EIO; goto fail;
}
/* give away socket */
spin_lock(&hc->socket_lock);
hc->socket = socket;
spin_unlock(&hc->socket_lock);
/* read loop */ if (debug & DEBUG_L1OIP_SOCKET)
printk(KERN_DEBUG "%s: socket created and open\n",
__func__); while (!signal_pending(current)) {
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, recvbuf_size);
recvlen = sock_recvmsg(socket, &msg, 0); if (recvlen > 0) {
l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen);
} else { if (debug & DEBUG_L1OIP_SOCKET)
printk(KERN_WARNING "%s: broken pipe on socket\n", __func__);
}
}
/* get socket back, check first if in use, maybe by send function */
spin_lock(&hc->socket_lock); /* if hc->socket is NULL, it is in use until it is given back */ while (!hc->socket) {
spin_unlock(&hc->socket_lock);
schedule_timeout(HZ / 10);
spin_lock(&hc->socket_lock);
}
hc->socket = NULL;
spin_unlock(&hc->socket_lock);
if (debug & DEBUG_L1OIP_SOCKET)
printk(KERN_DEBUG "%s: socket thread terminating\n",
__func__);
fail: /* free recvbuf */
kfree(recvbuf);
/* close socket */ if (socket)
sock_release(socket);
/* if we got killed, signal completion */
complete(&hc->socket_complete);
hc->socket_thread = NULL; /* show termination of thread */
/* if active, we send up a PH_DEACTIVATE and deactivate */ if (test_bit(FLG_ACTIVE, &dch->Flags)) { if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
printk(KERN_DEBUG "%s: interface become deactivated " "due to timeout\n", __func__);
test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
_queue_data(&dch->dev.D, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
NULL, GFP_ATOMIC);
}
}
staticint
l1oip_socket_open(struct l1oip *hc)
{ /* in case of reopen, we need to close first */
l1oip_socket_close(hc);
init_completion(&hc->socket_complete);
/* create receive process */
hc->socket_thread = kthread_run(l1oip_socket_thread, hc, "l1oip_%s",
hc->name); if (IS_ERR(hc->socket_thread)) { int err = PTR_ERR(hc->socket_thread);
printk(KERN_ERR "%s: Failed (%d) to create socket process.\n",
__func__, err);
hc->socket_thread = NULL;
sock_release(hc->socket); return err;
} if (debug & DEBUG_L1OIP_SOCKET)
printk(KERN_DEBUG "%s: socket thread created\n", __func__);
if (debug & DEBUG_L1OIP_MSG)
printk(KERN_DEBUG "%s: timeout timer expired, turn layer one " "down.\n", __func__);
hc->timeout_on = 0; /* state that timer must be initialized next time */
/* if timeout, we send up a PH_DEACTIVATE and deactivate */ if (test_bit(FLG_ACTIVE, &dch->Flags)) { if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
printk(KERN_DEBUG "%s: interface become deactivated " "due to timeout\n", __func__);
test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
_queue_data(&dch->dev.D, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
NULL, GFP_ATOMIC);
}
/* if we have ondemand set, we remove ip address */ if (hc->ondemand) { if (debug & DEBUG_L1OIP_MSG)
printk(KERN_DEBUG "%s: on demand causes ip address to " "be removed\n", __func__);
hc->sin_remote.sin_addr.s_addr = 0;
}
}
switch (codec[l1oip_cnt]) { case0: /* as is */ case1: /* alaw */ case2: /* ulaw */ case3: /* 4bit */ break; default:
printk(KERN_ERR "Codec(%d) not supported.\n",
codec[l1oip_cnt]); return -EINVAL;
}
hc->codec = codec[l1oip_cnt]; if (debug & DEBUG_L1OIP_INIT)
printk(KERN_DEBUG "%s: using codec %d\n",
__func__, hc->codec);
if (id[l1oip_cnt] == 0) {
printk(KERN_WARNING "Warning: No 'id' value given or " "0, this is highly unsecure. Please use 32 " "bit random number 0x...\n");
}
hc->id = id[l1oip_cnt]; if (debug & DEBUG_L1OIP_INIT)
printk(KERN_DEBUG "%s: using id 0x%x\n", __func__, hc->id);
hc->ondemand = ondemand[l1oip_cnt]; if (hc->ondemand && !hc->id) {
printk(KERN_ERR "%s: ondemand option only allowed in " "conjunction with non 0 ID\n", __func__); return -EINVAL;
}
if (limit[l1oip_cnt])
hc->b_num = limit[l1oip_cnt]; if (!pri && hc->b_num > 2) {
printk(KERN_ERR "Maximum limit for BRI interface is 2 " "channels.\n"); return -EINVAL;
} if (pri && hc->b_num > 126) {
printk(KERN_ERR "Maximum limit for PRI interface is 126 " "channels.\n"); return -EINVAL;
} if (pri && hc->b_num > 30) {
printk(KERN_WARNING "Maximum limit for BRI interface is 30 " "channels.\n");
printk(KERN_WARNING "Your selection of %d channels must be " "supported by application.\n", hc->limit);
}
l1oip_cnt = 0; while (l1oip_cnt < MAX_CARDS && type[l1oip_cnt]) { switch (type[l1oip_cnt] & 0xff) { case1:
pri = 0;
bundle = 0; break; case2:
pri = 1;
bundle = 0; break; case3:
pri = 0;
bundle = 1; break; case4:
pri = 1;
bundle = 1; break; default:
printk(KERN_ERR "Card type(%d) not supported.\n",
type[l1oip_cnt] & 0xff);
l1oip_cleanup(); return -EINVAL;
}
if (debug & DEBUG_L1OIP_INIT)
printk(KERN_DEBUG "%s: interface %d is %s with %s.\n",
__func__, l1oip_cnt, pri ? "PRI" : "BRI",
bundle ? "bundled IP packet for all B-channels" : "separate IP packets for every B-channel");
hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC); if (!hc) {
printk(KERN_ERR "No kmem for L1-over-IP driver.\n");
l1oip_cleanup(); return -ENOMEM;
}
INIT_WORK(&hc->workq, (void *)l1oip_send_bh);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.