if you cast a ray from A to B, that ray you can hit planes C,D,E,F, etc. each plane has its own plane and normal.
distfromA = dotproduct(A, planenormal) - planedist;
distfromB = dotproduct(B, planenormal) - planedist;
fraction = distfromA / (distfromB-distfromA);
endpos = A + (B-A)*fraction;
if you're doing triangle-based collision, then there are 3 more dotproducts against endpos and the 3 planes that define the edges of the triangle.
brush collision does some traces against every single plane of the brush to figure out which plane it actually hit (furthest, so long as it wasn't clipped by another plane).
bsp collision provides an ordered tree of planes, with the results of plane checks determining which other leafs/planes need to be checked.
the actual trace that is returned by traceline is then the trace against the plane which resulted in the lowest fraction (where it actually hit the geometry that included that plane, and where the far side is considered solid with the near side not).
things get more messy when using traceboxes - the plane distances are expanded according to the size of the box. in the case of q1bsp these distances are precomputed, hence why only certain 'hull' sizes work correctly.
so yes, fraction is the (decimal)percentage of the distance travelled. 0 if it hit immediately, 50% if the wall was half of the distance away, and 1 if it travelled the full distance without hitting anything.
the startsolid flag is poorly defined. logic dictates that it can only be set when fraction is 1, which makes testing for it unreliable. often you'll want to ignore startsolid, because it can be better to allow traces through solids if you're already inside them as a way to attempt to counter any precision issues. alternatively you can do what nq player physics does, and just teleport the player back to their oldorigin if the player gets stuck.
the other contents flags are similarly unreliable, and reflect only the nearest impact. if you're pushing against a submodel while in water, if it detects and impact against that submodel then you won't be in water, but if you move away slightly then suddenly you will be. pointcontents is more reliable for this sort of thing.