e1input: rework generic (virtual and real) E1 line operations

struct e1inp_line_ops {
       int     (*sign_link_up)(struct msgb *msg, struct e1inp_line *line);
       int     (*sign_link)(struct msgb *msg, struct e1inp_sign_link *link);
       int     (*error)(struct msgb *msg, int error);
};

The description of the operations is the following:

* sign_link_up is invoked if the signalling link becomes up. In A-bis
over IP, we have to wait until the other peer identifies itself as
a BTS/BSC device, then this function is invoked. This function is not
used by ISDN drivers, the signalling link can be set up just after
the line is created.

* sign_link is called if we receive OML/RSL message. This function
is used both by ISDN and A-bis over IP drivers.

* error is called if we receive a malformed message. It is used both
by ISDN and A-bis over IP drivers.
diff --git a/src/e1_input.c b/src/e1_input.c
index 1c3d3b0..7904f61 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -305,8 +305,7 @@
 
 struct e1inp_line *
 e1inp_line_create(uint8_t e1_nr, const char *driver_name,
-		  int (*rx)(struct msgb *msgb, struct e1inp_ts *ts),
-		  int (*rx_err)(int error))
+		  const struct e1inp_line_ops *ops)
 {
 	struct e1inp_driver *driver;
 	struct e1inp_line *line;
@@ -331,8 +330,7 @@
 		return NULL;
 
 	line->driver = driver;
-	line->rx = rx;
-	line->rx_err = rx_err;
+	memcpy(&line->ops, ops, sizeof(struct e1inp_line_ops));
 
 	line->num = e1_nr;
 	for (i = 0; i < NUM_E1_TS; i++) {
@@ -467,10 +465,12 @@
 				"tei %d, sapi %d\n", tei, sapi);
 			return -EINVAL;
 		}
-		if (!ts->line->rx)
-			printf("XXX Error, horror\n");
-
-		ts->line->rx(msg, ts);
+		if (!ts->line->ops.sign_link) {
+	                LOGP(DINP, LOGL_ERROR, "Fix your application, "
+				"no action set for signalling messages.\n");
+			return -ENOENT;
+		}
+		ts->line->ops.sign_link(msg, link);
 		break;
 	case E1INP_TS_TYPE_TRAU:
 		ret = subch_demux_in(&ts->trau.demux, msg->l2h, msgb_l2len(msg));