Forc­ing a route in Solaris?

I have a lit­tle prob­lem find­ing a clean solu­tion to the fol­low­ing problem.

A machine with two net­work inter­faces and no default route. The first inter­face gets an IP at boot time and the cor­re­spond­ing sta­t­ic route is insert­ed dur­ing boot into the rout­ing table with­out prob­lems. The sec­ond inter­face only gets an IP address when the shared-IP zones on the machine are start­ed, dur­ing boot the inter­face is plumbed but with­out any address. The net­works on those inter­faces are not con­nect­ed and the machine is not a gate­way (this means we have a machine-administration net­work and a production-network). The sta­t­ic routes we want to have for the address­es of the zones are not added to the rout­ing table, because the next hop is not reach­able at the time the routing-setup is done. As soon as the zones are up (and the inter­face gets an IP), a re-run of the routing-setup adds the miss­ing sta­t­ic routes.

Unfor­tu­nate­ly I can not tell Solaris to keep the sta­t­ic route even if the next hop is not reach­able ATM (at least I have not found an option to the route com­mand which does this).

One solu­tion to this prob­lem would be to add an address at boot to the inter­face which does not have an address at boot-time ATM (prob­a­bly with the dep­re­cat­ed flag set). The prob­lem is, that this sub­net (/28) has not enough free address­es any­more, so this is not an option.

Anoth­er solu­tion is to use a script which re-runs the routing-setup after the zones are start­ed. This is a prag­mat­ic solu­tion, but not a clean solution.

As I under­stand the in.routed man-page in.routed is not an option with the default con­fig, because the machine shall not route between the net­works, and shall not change the rout­ing based upon RIP mes­sages from oth­er machines. Unfor­tu­nate­ly I do not know enough about it to be sure, and I do not get the time to play around with this. I have seen some inter­st­ing options regard­ing this in the man-page, but play­ing around with this and sniff­ing the net­work to see what hap­pens, is not an option ATM. Any­one with a config/tutorial for this “do not broad­cast any­thing, do not accept any­thing from outside”-case (if possible)?

Sony BRAVIA TV & DLNA formats

As I wrote ear­li­er, I try to get some infos which for­mats my Sony BRAVIA 5800 TV is able to play over the net­work. Sony is not real­ly help­ful (they tell only names some­one with a DLNA spec could cor­rect­ly inter­pret). Now I took the time to move my TV into a dif­fer­ent sub­net (the same where my NAS is in, not like before in a DMZ), and I installed minidl­na. After some net­work sniff­ing, the use of the Intel UPnP Device Spy and some minidlna-source read­ing I have now a bet­ter idea what my Sony TV expects.

The DLNA-specification seems to man­date a MIME-type and some DLNA-specific iden­ti­fi­er which describes the con­tent a play­er (a DLNA-Renderer) is able to dis­play. In the fol­low­ing I will present the MIME-type, the DLNA-identifier, and prob­a­bly a Sony-specific identifier.

Regard­ing pic­tures the TV only accepts JPEGs, bit in small, medi­um and large sizes. I did not both­er to look up what this means in real val­ues, so far this is not of high inter­est for me. For audio the TV accepts MP3s and LPCM (raw PCM sam­ples). The raw sniffed data from the TV looks like this:

image/jpeg:DLNA.ORG_PN=JPEG_SM
image/jpeg:DLNA.ORG_PN=JPEG_MED
image/jpeg:DLNA.ORG_PN=JPEG_LRG
audio/mpeg:DLNA.ORG_PN=MP3
audio/L16:DLNA.ORG_PN=LPCM

The more inter­est­ing part for me is the video part. The TV sup­ports MPEG2 Video (the MPEG_ part in the DLNA.ORG_PN) and H.264 (the AVC_ part in the DLNA.ORG_PN). For MPEG2 it sup­ports pro­gram streams (PS in DLNA.ORG_PN) and trans­port streams (TS in DLNA.ORG_PN). For PS it sup­ports PAL and NTSC res­o­lu­tions (720×576 is PAL, HD res­o­lu­tions like 720p or 1080i or 1080p are not sup­port­ed). The packet-length of a trans­port steam can be 188 bytes or 192 bytes. If the width is >= 1288 or the height is >= 720, minidl­na adds HD in DLNA.ORG_PN, else it will add SD. The EU in DLNA.ORG_PN is for SD video with a height of 576 or 288 pix­els. Depend­ing of the com­bi­na­tion of the packet-length and if there is a time­stamp in use or not, the DLNA.ORG_PN will have a _ISO or a _T appended.

It also sup­ports H.264. The DLNA.ORG_PN starts with a AVC in this case. Only trans­port streams (TS  in DLNA.ORG_PN) is sup­port­ed. As with MPEG2, the packet-length of the TS can be 188 or 192 bytes. Depend­ing of the com­bi­na­tion of the packet-length and if there is a time­stamp in use or not, the DLNA.ORG_PN will have a _ISO or a _T append­ed. Depend­ing on the pro­file used, minidl­na adds some more infos to the DLNA.ORG_PN, BL if it is a baseline-profile, MP if it is a main-profile, and HP if it is a high-profile. I do not see this in the valid video for­mats my TV request­ed over the wire. As with the MPEG2 for­mat, SD or HD is added (in minidl­na) depend­ing on the width and height, but also on the bitrate of the video. For the main-profile the width has to be <= 720, the height <= 576 and the bitrate <= 10M (base 10, not base 2) for SD, and the width has to be <=1920, the height <= 1152 and the bitrate <= 20M (base 10, not base 2) for HD. For the high-profile the width has to be <=1920, the height <=1152, the bitrate <= 30M (base 10, not base 2) and the audio has to be AC3 to get the HD added in DLNA.ORG_PN. The audio is spec­i­fied in DLNA.ORG_PN as MPEG1_L3 for MP3, AC3 for AC3, and AAC or AAC_MULT5 for AAC (stereo or 5‑channel). As can be seen below, the TV seems only to sup­port AC3 audio for AVC. The TV also has _24_, _50_ and _60_ in DLNA.ORG_PN. I did not find those things in the minidl­na source (but I have not real­ly searched for this). I could imag­ine that _24_ stands for 24 pic­tures per sec­ond, and the _50_ and _60_ for pro­gres­sive videos (with 50 respec­tive­ly 60 pic­tures per sec­ond), but this is pure spec­u­la­tion from my side. Here is the raw sniffed data:

video/mpeg:DLNA.ORG_PN=AVC_TS_HD_24_AC3_ISO;SONY.COM_PN=AVC_TS_HD_24_AC3_ISO
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_24_AC3;SONY.COM_PN=AVC_TS_HD_24_AC3
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_24_AC3_T;SONY.COM_PN=AVC_TS_HD_24_AC3_T

video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_PS_PAL
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_PS_NTSC

video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_50_L2_T
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_60_L2_T
video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_50_AC3_T
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_60_AC3_T
video/mpeg:DLNA.ORG_PN=MPEG_TS_HD_50_L2_ISO;SONY.COM_PN=HD2_50_ISO
video/mpeg:DLNA.ORG_PN=MPEG_TS_HD_60_L2_ISO;SONY.COM_PN=HD2_60_ISO
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_HD_50_L2_T;SONY.COM_PN=HD2_50_T
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_HD_60_L2_T;SONY.COM_PN=HD2_60_T

video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;SONY.COM_PN=AVC_TS_HD_50_AC3_ISO
video/mpeg:DLNA.ORG_PN=AVC_TS_HD_60_AC3_ISO;SONY.COM_PN=AVC_TS_HD_60_AC3_ISO
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;SONY.COM_PN=AVC_TS_HD_50_AC3
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_60_AC3;SONY.COM_PN=AVC_TS_HD_60_AC3
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;SONY.COM_PN=AVC_TS_HD_50_AC3_T
video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_60_AC3_T;SONY.COM_PN=AVC_TS_HD_60_AC3_T

video/x-mp2t-mphl-188

So far I did not get the time to exper­i­ment with this. I also have the impres­sion that minidl­na has still some rough edges (the sin­tel video I used to test before with a dif­fer­ent media serv­er, does not show up in the list with minidlna).

Lin­ux­u­la­tor explained (for devel­op­ers): adding ioctls direct­ly to the kernel

After giv­ing an overview of the in-kernel basics of the Lin­ux­u­la­tor, I want now to describe how to add sup­port for new ioctls to the Linuxulator.

Where are the files to modify?

The plat­form inde­pen­dent code for the ioctls is in SRC/sys/compat/linux/linux_ioctl.c. The defines to have names for the ioctl val­ues are in SRC/sys/compat/linux/linux_ioctl.h.

How to mod­i­fy them?

First of all cre­ate a new head­er which will con­tain all the struc­tures, named val­ues and macros for those new ioctls. As writ­ten above, the ioctl val­ues (e.g. #define LINUX_VIDIOC_ENCODER_CMD 0x564d /* 0xc028564d */) do not belong there, they shall be added to linux_ioctl.h. Dur­ing the course of adding sup­port for ioctls, you will need this new head­er. Add it in the SRC/sys/compat/linux/ direc­to­ry, and pre­fix the name with a linux_. It would be good to decide on a com­mon tag here (ref­er­enced as yourtag in the fol­low­ing), and stay with it. Use it wher­ev­er you need to have some spe­cif­ic name for the ioctl-set you want to add. In this case it would result in linux_yourtag.h (or even linux_ioctl_yourtag.h, depend­ing if this is used for some­thing very spe­cif­ic to the ioctls, or some gener­ic lin­ux fea­ture) as the name of the head­er file. This was not done in the past, so do not expect that the names inside the linux_ioctl.c file will be con­sis­tent to this nam­ing scheme, but it is nev­er too late to cor­rect mis­takes of the past (at least in Open Source soft­ware development).

Now add this head­er to linux_ioctl.c (you need to include compat/linux/linux_yourtag.h). After that add the ioctl val­ues to linux_ioctl.h. As can be seen above, the defines should be named the same as on lin­ux, but with a LINUX_ pre­fix (make sure they where not defined before some­where else). The ioctl val­ues need to be the same hex val­ues as in Lin­ux, off course. Sort them accord­ing to their hex val­ue. When you added all, you need to add two more defines. The LINUX_IOCTL_yourtag_MIN and LINUX_IOCTL_yourtag_MAX ones. The MIN-one needs to be an alias for the first (sort­ed accord­ing to the hex val­ue) ioctl you added, and MAX needs to be an alias for the last (again, sort­ed accord­ing to the hex val­ue) ioctl you added.

The next step is to let the Lin­ux­u­la­tor know that it is able to han­dle the ioctls in the LINUX_IOCTL_yourtag_MIN to LINUX_IOCTL_yourtag_MAX range. Search the sta­t­ic linux_ioctl_function_t sec­tion of linux_ioctl.c and add such a vari­able for your ioctl set. The name of the vari­able should be some­thing like linux_ioctl_yourtag.

Sim­i­lar for the handler-definition for this. Search the sta­t­ic struct linux_ioctl_handler sec­tion and add a yourtag_handler. Set it to { linux_ioctl_yourtag, LINUX_IOCTL_yourtag_MIN, LINUX_IOCTL_yourtag_MAX }. To make this han­dler known to the Lin­ux­u­la­tor, you need to add it to the DATA_SET sec­tion. Add DATA_SET(linux_ioctl_handler_set, yourtag_handler) there.

Now the meat, the func­tion which han­dles the ioctls. You already defined it as linux_ioctl_function_t, but now you need to write it. The out­line of it looks like this:

static int
linux_ioctl_yourtag(struct thread *td, struct linux_ioctl_args *args)
{
        struct file *fp;
        int error;
        switch (args->cmd & 0xffff) {
        case LINUX_an_easy_ioctl:
                break;
        case LINUX_a_not_so_easy_ioctl:
                /* your handling of the ioctl */
                fdrop(fp, td);
                return (error);
        /* some more handling of your ioctls */
        default:
       return (ENOIOCTL);
        }
        error = ioctl(td, (struct ioctl_args *)args);
        return (error);
}

An easy ioctl in the switch above is an ioctl where you do not have to do some­thing but can pass the ioctl through to FreeB­SD itself. The not so easy ioctl case is an ioctl where you need to do e.g. a fget(td, args->fd, &fp). This is just an exam­ple, there are also oth­er pos­si­bil­i­ties where you need to do addi­tion­al stuff before the return, or where you do not pass the ioctl to FreeB­SD. A typ­i­cal exam­ple of what needs to be done here is to copy val­ues from lin­ux struc­tures to FreeB­SD struc­tures (and the oth­er way too), or to trans­late between 64bit and 32bit. Lin­ux pro­grams on amd64 are 32bit exe­cuta­bles and 32bit structures/pointers. To make this work on amd64, you need to find a way to map between the two. There are exam­ples in the ker­nel where this is already the case. The more promi­nent exam­ples in the 64bit<->32bit regard are the v4l and v4l2 ioctls.

The tedious part is to research if a trans­la­tion has to be done and if yes what needs to be trans­lat­ed how. When this is done, most of the work is not so hard. The linux_yourtag.h should con­tain the struc­tures you need for this trans­la­tion work.

It is also pos­si­ble to add ioctls in a ker­nel mod­ule, but this is not sub­ject to this descrip­tion (I will update this post­ing with a link to it when I get time to write about it).

(Free)BSD inside Android

Today I was look­ing into the Open­Source licens­es which are dis­played for Android (2.3.4). There are sev­er­al files which come with a BSD license.

Dur­ing look­ing at it, I noticed that the libm has the copy­right of sev­er­al FreeB­SD peo­ple. I did not had an in-deep look if this is because they took the FreeB­SD libm, or if this is because parts of the FreeB­SD libm where adopt­ed by oth­er BSD projects.

What I noticed is, that some spe­cial char­ac­ters are not dis­played cor­rect­ly. For exam­ple the name Dag-Erling Smør­grav looks man­gled in the dis­play of the license inside the phone (I hope it is dis­played bet­ter in my blog). His name is not the only prob­lem case, there are also oth­er char­ac­ters which are not ren­dered as expected.

This does not real­ly look professional.